source: trunk/libtransmission/completion.c @ 5

Last change on this file since 5 was 5, checked in by root, 15 years ago

Update 2005-11-18

File size: 7.0 KB
Line 
1/******************************************************************************
2 * Copyright (c) 2005 Eric Petit
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *****************************************************************************/
22
23#include "transmission.h"
24
25tr_completion_t * tr_cpInit( tr_torrent_t * tor )
26{
27    tr_completion_t * cp;
28
29    cp                   = malloc( sizeof( tr_completion_t ) );
30    cp->tor              = tor;
31    cp->blockBitfield    = malloc( ( tor->blockCount + 7 ) / 8 );
32    cp->blockDownloaders = malloc( tor->blockCount );
33    cp->pieceBitfield    = malloc( ( tor->info.pieceCount + 7 ) / 8 );
34    cp->missingBlocks    = malloc( tor->info.pieceCount * sizeof( int ) );
35
36    tr_cpReset( cp );
37
38    return cp;
39}
40
41void tr_cpClose( tr_completion_t * cp )
42{
43    free( cp->blockBitfield );
44    free( cp->blockDownloaders );
45    free( cp->pieceBitfield );
46    free( cp->missingBlocks );
47    free( cp );
48}
49
50void tr_cpReset( tr_completion_t * cp )
51{
52    tr_torrent_t * tor = cp->tor;
53    int i;
54
55    cp->blockCount = 0;
56    memset( cp->blockBitfield,    0, ( tor->blockCount + 7 ) / 8 );
57    memset( cp->blockDownloaders, 0, tor->blockCount );
58    memset( cp->pieceBitfield,    0, ( tor->info.pieceCount + 7 ) / 8 );
59    for( i = 0; i < tor->info.pieceCount; i++ )
60    {
61        cp->missingBlocks[i] = tr_pieceCountBlocks( i );
62    }
63}
64
65float tr_cpCompletionAsFloat( tr_completion_t * cp )
66{
67    return (float) cp->blockCount / (float) cp->tor->blockCount;
68}
69
70uint64_t tr_cpLeftBytes( tr_completion_t * cp )
71{
72    tr_torrent_t * tor = cp->tor;
73    uint64_t left;
74    left = (uint64_t) ( cp->tor->blockCount - cp->blockCount ) *
75           (uint64_t) tor->blockSize;
76    if( !tr_bitfieldHas( cp->blockBitfield, cp->tor->blockCount - 1 ) &&
77        tor->info.totalSize % tor->blockSize )
78    {
79        left += tor->info.totalSize % tor->blockSize;
80        left -= tor->blockSize;
81    }
82    return left;
83}
84
85/* Pieces */
86int tr_cpPieceIsComplete( tr_completion_t * cp, int piece )
87{
88    return tr_bitfieldHas( cp->pieceBitfield, piece );
89}
90
91uint8_t * tr_cpPieceBitfield( tr_completion_t * cp )
92{
93    return cp->pieceBitfield;
94}
95
96void tr_cpPieceAdd( tr_completion_t * cp, int piece )
97{
98    tr_torrent_t * tor = cp->tor;
99    int startBlock, endBlock, i;
100
101    startBlock = tr_pieceStartBlock( piece );
102    endBlock   = startBlock + tr_pieceCountBlocks( piece );
103    for( i = startBlock; i < endBlock; i++ )
104    {
105        tr_cpBlockAdd( cp, i );
106    }
107
108    tr_bitfieldAdd( cp->pieceBitfield, piece );
109}
110
111/* Blocks */
112void tr_cpDownloaderAdd( tr_completion_t * cp, int block )
113{
114    tr_torrent_t * tor = cp->tor;
115    if( !cp->blockDownloaders[block] && !tr_cpBlockIsComplete( cp, block ) )
116    {
117        cp->missingBlocks[tr_blockPiece(block)]--;
118    }
119    (cp->blockDownloaders[block])++;
120}
121
122void tr_cpDownloaderRem( tr_completion_t * cp, int block )
123{
124    tr_torrent_t * tor = cp->tor;
125    (cp->blockDownloaders[block])--;
126    if( !cp->blockDownloaders[block] && !tr_cpBlockIsComplete( cp, block ) )
127    {
128        cp->missingBlocks[tr_blockPiece(block)]++;
129    }
130}
131
132int tr_cpBlockIsComplete( tr_completion_t * cp, int block )
133{
134    return tr_bitfieldHas( cp->blockBitfield, block );
135}
136
137void tr_cpBlockAdd( tr_completion_t * cp, int block )
138{
139    tr_torrent_t * tor = cp->tor;
140    if( !tr_cpBlockIsComplete( cp, block ) )
141    {
142        (cp->blockCount)++;
143        if( !cp->blockDownloaders[block] )
144        {
145            (cp->missingBlocks[tr_blockPiece(block)])--;
146        }
147    }
148    tr_bitfieldAdd( cp->blockBitfield, block );
149}
150
151void tr_cpBlockRem( tr_completion_t * cp, int block )
152{
153    tr_torrent_t * tor = cp->tor;
154    if( tr_cpBlockIsComplete( cp, block ) )
155    {
156        (cp->blockCount)--;
157        if( !cp->blockDownloaders[block] )
158        {
159            (cp->missingBlocks[tr_blockPiece(block)])++;
160        }
161    }
162    tr_bitfieldRem( cp->blockBitfield, block );
163}
164
165uint8_t * tr_cpBlockBitfield( tr_completion_t * cp )
166{
167    return cp->blockBitfield;
168}
169
170void tr_cpBlockBitfieldSet( tr_completion_t * cp, uint8_t * bitfield )
171{
172    tr_torrent_t * tor = cp->tor;
173    int i, j;
174    int startBlock, endBlock;
175    int pieceComplete;
176
177    for( i = 0; i < cp->tor->info.pieceCount; i++ )
178    {
179        startBlock    = tr_pieceStartBlock( i );
180        endBlock      = startBlock + tr_pieceCountBlocks( i );
181        pieceComplete = 1;
182
183        for( j = startBlock; j < endBlock; j++ )
184        {
185            if( tr_bitfieldHas( bitfield, j ) )
186            {
187                tr_cpBlockAdd( cp, j );
188            }
189            else
190            {
191                pieceComplete = 0;
192            }
193        }
194        if( pieceComplete )
195        {
196            tr_cpPieceAdd( cp, i );
197        }
198    }
199}
200
201int tr_cpMissingBlockInPiece( tr_completion_t * cp, int piece )
202{
203    tr_torrent_t * tor = cp->tor;
204    int start, count, end, i;
205
206    start = tr_pieceStartBlock( piece );
207    count = tr_pieceCountBlocks( piece );
208    end   = start + count;
209
210    for( i = start; i < end; i++ )
211    {
212        if( tr_cpBlockIsComplete( cp, i ) || cp->blockDownloaders[i] )
213        {
214            continue;
215        }
216        return i;
217    }
218
219    return -1;
220}
221
222int tr_cpMostMissingBlockInPiece( tr_completion_t * cp, int piece,
223                                  int * downloaders )
224{
225    tr_torrent_t * tor = cp->tor;
226    int start, count, end, i;
227    int * pool, poolSize, min, ret;
228
229    start = tr_pieceStartBlock( piece );
230    count = tr_pieceCountBlocks( piece );
231    end   = start + count;
232
233    pool     = malloc( count * sizeof( int ) );
234    poolSize = 0;
235    min      = 255;
236
237    for( i = start; i < end; i++ )
238    {
239        if( tr_cpBlockIsComplete( cp, i ) || cp->blockDownloaders[i] > min )
240        {
241            continue;
242        }
243        if( cp->blockDownloaders[i] < min )
244        {
245            min      = cp->blockDownloaders[i];
246            poolSize = 0;
247        }
248        if( cp->blockDownloaders[i] <= min )
249        {
250            pool[poolSize++] = i;
251        }
252    }
253
254    if( poolSize < 1 )
255    {
256        return -1;
257    }
258
259    ret = pool[0];
260    free( pool );
261    *downloaders = min;
262    return ret;
263}
264
Note: See TracBrowser for help on using the repository browser.