source: trunk/libtransmission/completion.c @ 260

Last change on this file since 260 was 260, checked in by titer, 15 years ago

Added $Id$ keywords and updated a few headers

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