?? btcontent.cpp
字號:
#include "Btcontent.h"#include <math.h>#include "Sha.h"#include "Tracker.h"#include <iostream.h>//////problem//1.how to set the cache size?//2.how to adjust the cache size dynamically?#define DEBUG(fmt, ...) fprintf (stderr, fmt, __VA_ARGS__)#define max_uint64_t(a, b) ((uint64_t)(a) > (uint64_t)(b)) ? \(uint64_t) (a):(uint64_t) (b)#define min_uint64_t(a, b) \ ((uint64_t) (a) > (uint64_t) (b)) ? \ (uint64_t) (b) : (uint64_t) (a)#define CACHE_HIT(p, offset, len) \(max_uint64_t((p)->bc_off, (offset)) < min_uint64_t((p)->bc_off + (p)->bc_len, offset + len))btContent BTCONTENT;btContent::btContent(){ m_announce = NULL; m_pbitmap = NULL; m_create_date = (time_t) 0; m_hash_table = NULL; m_npieces = 0; m_piece_length = 0; m_left_bytes = 0; m_cache_oldest = NULL; m_cache_newest = NULL; m_cache_size = 16 * 1024; // how to set the cache size? m_cache_used = 0; memset(m_announce_list, 0, sizeof(char*)*20);}btContent::~btContent(){ delete m_announce; delete m_hash_table; delete m_cache; free_announce_list(); empty_cache();}void btContent::free_announce_list(){ char** p = m_announce_list; for(; *p; p++) delete [] (*p);}void btContent::empty_cache(){ BTCACHE *p = m_cache_newest, *pp = NULL; for (; p;) { pp = p->age_next; delete[]p->bc_buf; delete p; p = pp; }}int btContent::InitialFromMI(Bencode * pcode){ int i = 0; Bencode* bp; std::string keylist; keylist = "announce"; if (!search_dictionary(pcode, keylist, (char **) &m_announce, NULL)) return -1; if(m_announce) { m_announce_list[i] = (char*)m_announce; i++; } keylist = "announce-list"; if(NULL !=(bp = query_dict(pcode, keylist))) { if(bp->m_enumType != bencode_list) return -1; std::vector<Bencode*>::iterator iter, iter_end; iter = ((BencodeList*)bp)->m_list.begin(); iter_end = ((BencodeList*)bp)->m_list.end(); for(;iter != iter_end; iter++) { BencodeList* plist; std::vector<Bencode*>::iterator iter1, iter1_end; plist = (BencodeList*)(*iter); if(plist->m_enumType != bencode_list) continue; iter1 = plist->m_list.begin(); iter1_end = plist->m_list.end(); for(; iter1 != iter1_end; iter1++ ) { BencodeString* pstr; pstr = (BencodeString*)(*iter1); int slen = pstr->m_strValue.length(); cout << pstr->m_strValue; m_announce_list[i] = new char [slen + 1]; memcpy(m_announce_list[i], pstr->m_strValue.c_str(), slen); m_announce_list[i][slen] = '\0'; cout<<m_announce_list[i]<<endl; i++; } } } cout<<"asdfasdfsadf"<<endl; keylist = "creation date"; if (!search_dictionary(pcode, keylist, NULL, (int *) &m_create_date)) return -1; keylist = "info|pieces"; if (!search_dictionary (pcode, keylist, (char **) &m_hash_table, (int *) &m_hash_table_length) || m_hash_table_length % 20 != 0) return -1; m_npieces = m_hash_table_length / 20; keylist = "info|piece length"; if (!search_dictionary(pcode, keylist, NULL, (int *) &m_piece_length)) return -1; if (m_btfiles.BuildFromMI(pcode) < 0 /*|| m_btfiles.CreateFiles() < 0*/) return -1;/* size_t n = m_btfiles.GetTotalLength() / m_piece_length + (m_btfiles.GetTotalLength() % m_piece_length ? 1 : 0); if (n != m_npieces) return -1; m_left_bytes = m_btfiles.GetTotalLength();*/ m_cache = new BTCACHE *[m_npieces]; if (NULL == m_cache) { DEBUG("%s\n", "error! can't allocate the cache index memory"); return -1; } memset(m_cache, 0, sizeof(BTCACHE *) * m_npieces); m_sha_buffer = new unsigned char[m_piece_length]; if (NULL == m_sha_buffer) { DEBUG("%s\n", "error! can't allocate the sha buffer"); return -1; } m_pbitmap = new bitfield(m_npieces);// memset(m_shake_buffer, 0, 68); unsigned char *p = m_shake_buffer; *p = (unsigned char) 19; p++; memcpy(p, "BitTorrent protocol", 19); p += 19; memset(p, 0, 8); p = m_shake_buffer + 48; memcpy(p, "-CD0300-", 8); p += 8; unsigned char *dptr = p + 12; while (dptr != p) *p++ = (unsigned char) random(); return 0;}size_t btContent::GetPieceLength(size_t idx){ return (idx == m_btfiles.GetTotalLength() / m_piece_length) ? m_btfiles.GetTotalLength() % m_piece_length : m_piece_length;}int btContent::APieceComplete(size_t idx){ unsigned char md[20]; if (m_pbitmap->IsSet(idx)) return 1; if (GetHashValue(idx, md) < 0) { Uncache(idx); //since error, uncache it return -1; } if (memcmp(m_hash_table + idx * 20, md, 20) != 0) return 0; m_pbitmap->Set(idx); m_left_bytes -= GetPieceLength(idx); FlushCache(idx); return 1;}void btContent::Uncache(size_t idx){ BTCACHE *p, *pnext; for (p = m_cache[idx]; p && (p->bc_off / m_piece_length == idx);) { pnext = p->bc_next; if (p->bc_prev) p->bc_prev->bc_next = p->bc_next; else m_cache[idx] = p->bc_next; if (p->bc_next) p->bc_next->bc_prev = p->bc_prev; if (p->age_next) p->age_next->age_prev = p->age_prev; else m_cache_oldest = p->age_prev; if (p->age_prev) p->age_prev->age_next = p->age_next; else m_cache_newest = p->age_next; m_cache_used -= p->bc_len; delete[]p->bc_buf; delete p; p = pnext; } if (NULL != m_cache[idx]) DEBUG("%s\n", "uncache error!");}int btContent::GetHashValue(size_t idx, unsigned char *md){ if (GetAPiece(idx, m_sha_buffer) < 0) return -1; Sha1(m_sha_buffer, GetPieceLength(idx), md); return 0;}int btContent::GetAPiece(size_t idx, unsigned char *buf){ return ReadSlice(buf, idx, 0, GetPieceLength(idx));}ssize_t btContent::CacheIO(unsigned char *buf, uint64_t off, size_t len, int method){ BTCACHE *pnew, **p, *pp; int idx, piece; ssize_t ret = 0; if (m_cache_size < m_cache_used + len) CacheClean(len); if (0 == method && buf && (m_btfiles.IO((char *) buf, off, len, method) < 0)) return -1; pnew = new BTCACHE; if (NULL == p) return ret; pnew->bc_buf = new char[len]; if (NULL == pnew->bc_buf) { delete pnew; return ret; } pnew->bc_off = off; pnew->bc_len = len; pnew->bc_f_flush = method; m_cache_used += len; memcpy(pnew->bc_buf, buf, len); idx = off / m_piece_length; p = &m_cache[idx]; pp = m_cache[idx]; for (; p && *p && (*p)->bc_off < off; pp = *p, p = &((*p)->bc_next)); pnew->bc_next = *p; if (*p) (*p)->bc_prev = pnew; pnew->bc_prev = pp; *p = pnew; pp = m_cache_newest; if (pp) pp->age_prev = pnew; pnew->age_prev = NULL; pnew->age_next = pp; if (NULL == m_cache_oldest) m_cache_oldest = pnew; m_cache_newest = pnew; return ret;}void btContent::FlushCache(size_t idx){ BTCACHE *p; if (idx == m_npieces) p = m_cache_oldest; else p = m_cache[idx]; for (; p; p = (idx < m_npieces) ? p->bc_next : p->age_prev) { if (!p->bc_f_flush || (idx < m_npieces && p->bc_off / m_piece_length != idx)) continue; if (m_btfiles.IO(p->bc_buf, p->bc_off, p->bc_len, 1) < 0) DEBUG("%s", "can't flush the cache"); p->bc_f_flush = 0; if (p == m_cache_newest) continue;/* if (p->age_prev) p->age_prev->age_next = p->age_next; if (p->age_next) p->age_next->age_prev = p->age_prev; else if (p->age_prev) m_cache_oldest = p->age_prev; m_cache_newest->age_prev = p; p->age_prev = NULL; p->age_next = m_cache_newest; m_cache_newest = p;*/ }}void btContent::CacheClean(size_t need){ BTCACHE *p, *pnext; bool is_flushed = false; again: for (p = m_cache_oldest; p && m_cache_size < m_cache_used + need; p = pnext) { pnext = p->age_prev; if (p->bc_f_flush) continue; if (p->age_prev) p->age_prev->age_next = p->age_next; else m_cache_newest = p->age_next; if (p->age_next) p->age_next->age_prev = p->age_prev; else m_cache_oldest = p->age_prev; size_t idx = p->bc_off / m_piece_length; if (p->bc_next) p->bc_next->bc_prev = p->bc_prev; if (p->bc_prev) p->bc_prev->bc_next = p->bc_next; else m_cache[idx] = p->bc_next; m_cache_used += p->bc_len; delete p->bc_buf; delete p; } if (m_cache_size < m_cache_used + need && m_cache_used && !is_flushed) { FlushCache(); is_flushed = true; goto again; }}ssize_t btContent::ReadSlice(unsigned char *buf, size_t idx, size_t off, size_t len){ BTCACHE *p; ssize_t retval = 0; uint64_t offset = idx * m_piece_length + off; p = m_cache[idx]; for (; p && !CACHE_HIT(p, offset, len); p = p->bc_next); size_t len2 = 0; bool rescan = false; for (; p && len && CACHE_HIT(p, offset, len);) { if (offset < p->bc_off) { if (CacheIO(buf, offset, p->bc_off - offset, 0) < 0) { cout << "cache failed" << endl; return -1; } len2 = p->bc_off - offset; rescan = true; } else if (offset > p->bc_off) { len2 = ((p->bc_off + p->bc_len) - offset) > len ? len : ((p->bc_off + p->bc_len) - offset); if (buf) memcpy(buf, p->bc_buf + offset - p->bc_off, len2); } else //equal { len2 = p->bc_len > len ? len : p->bc_len; if (buf) memcpy(buf, p->bc_buf, len2); } len -= len2; buf += len2; offset += len2; if (!rescan) p = p->bc_next; } if (len) { if (CacheIO(buf, offset, len, 0) < 0) { cout << "cache failed" << endl; return -1; } } return 0;}ssize_t btContent::WriteSlice(unsigned char *buf, size_t idx, size_t off,size_t len){ BTCACHE *p; uint64_t offset = idx * m_piece_length + off; if (NULL == buf) return -1; p = m_cache[idx]; for (; p && !CACHE_HIT(p, offset, len); p = p->bc_next); bool rescan = false; size_t len2 = 0; for (; p && len && CACHE_HIT(p, offset, len);) { if (p->bc_off > offset) { if (CacheIO(buf, offset, len, 1) < 0) return -1; len2 = p->bc_off - offset; rescan = true; } else if (p->bc_off < offset) { len2 = p->bc_len - offset + p->bc_off > len ? len : p->bc_len - offset + p->bc_off; memcpy(p->bc_buf + offset - p->bc_off, buf, len2); } else { len2 = p->bc_len > len ? len : p->bc_len; memcpy(p->bc_buf, buf, len2); } len -= len2; buf += len2; offset += len2; if (!rescan) p = p->bc_next; } if (len) { if (CacheIO(buf, offset, len, 1) < 0) { cout << "write cache failed " << endl; return -1; } } return 0;}ssize_t btContent::ReadPiece(size_t idx, unsigned char *buff){ return ReadSlice(buff, idx, 0, GetPieceLength(idx));}void btContent::printout(){ BTCACHE *p = m_cache_newest; char *q; int i = 0; for (; i < 100; i++) { for (p = m_cache[i]; p; p = p->bc_next) { printf("%d\n", p->bc_off); int k = 0; for (q = p->bc_buf; k < p->bc_len; q++, k++) printf("%c", *q); printf("\n"); } } /* p = m_cache_oldest; for (; p; p = p->age_prev) { printf("%d\n", p->bc_off); for (q = p->bc_buf, i = 0; i < p->bc_len; q++, i++) printf("%c", *q); printf("\n"); } */}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -