source: trunk/libtransmission/completion.c @ 12262

Last change on this file since 12262 was 12262, checked in by jordan, 11 years ago

(trunk libT) handle situations where we don't know the bitfield's upper bound in advance. This comes up sometimes with magnet links.

  • Property svn:keywords set to Date Rev Author Id
File size: 7.0 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: completion.c 12262 2011-03-30 04:14:57Z jordan $
11 */
12
13#include "transmission.h"
14#include "completion.h"
15#include "torrent.h"
16#include "utils.h"
17
18/***
19****
20***/
21
22static void
23tr_cpReset( tr_completion * cp )
24{
25    cp->sizeNow = 0;
26    cp->sizeWhenDoneIsDirty = true;
27    cp->haveValidIsDirty = true;
28    tr_bitfieldSetHasNone( &cp->blockBitfield );
29}
30
31void
32tr_cpConstruct( tr_completion * cp, tr_torrent * tor )
33{
34    cp->tor = tor;
35    tr_bitfieldConstruct( &cp->blockBitfield, tor->blockCount );
36    tr_cpReset( cp );
37}
38
39void
40tr_cpBlockInit( tr_completion * cp, const tr_bitfield * b )
41{
42    tr_cpReset( cp );
43
44    /* set blockBitfield */
45    tr_bitfieldSetFromBitfield( &cp->blockBitfield, b );
46
47    /* set sizeNow */
48    cp->sizeNow = tr_bitfieldCountTrueBits( &cp->blockBitfield );
49    cp->sizeNow *= cp->tor->blockSize;
50    if( tr_bitfieldHas( b, cp->tor->blockCount-1 ) )
51        cp->sizeNow -= ( cp->tor->blockSize - cp->tor->lastBlockSize );
52}
53
54/***
55****
56***/
57
58tr_completeness
59tr_cpGetStatus( const tr_completion * cp )
60{
61    if( tr_cpHasAll( cp ) ) return TR_SEED;
62    if( !tr_torrentHasMetadata( cp->tor ) ) return TR_LEECH;
63    if( cp->sizeNow == tr_cpSizeWhenDone( cp ) ) return TR_PARTIAL_SEED;
64    return TR_LEECH;
65}
66
67void
68tr_cpPieceRem( tr_completion *  cp, tr_piece_index_t piece )
69{
70    tr_block_index_t i, f, l;
71    const tr_torrent * tor = cp->tor;
72
73    tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
74
75    for( i=f; i<=l; ++i )
76        if( tr_cpBlockIsComplete( cp, i ) )
77            cp->sizeNow -= tr_torBlockCountBytes( tor, i );
78
79    cp->haveValidIsDirty = true;
80    cp->sizeWhenDoneIsDirty = true;
81    tr_bitfieldRemRange( &cp->blockBitfield, f, l+1 );
82}
83
84void
85tr_cpPieceAdd( tr_completion * cp, tr_piece_index_t piece )
86{
87    tr_block_index_t i, f, l;
88    tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
89
90    for( i=f; i<=l; ++i )
91        tr_cpBlockAdd( cp, i );
92}
93
94void
95tr_cpBlockAdd( tr_completion * cp, tr_block_index_t block )
96{
97    const tr_torrent * tor = cp->tor;
98
99    if( !tr_cpBlockIsComplete( cp, block ) )
100    {
101        tr_bitfieldAdd( &cp->blockBitfield, block );
102        cp->sizeNow += tr_torBlockCountBytes( tor, block );
103
104        cp->haveValidIsDirty = true;
105        cp->sizeWhenDoneIsDirty = true;
106    }
107}
108
109/***
110****
111***/
112
113uint64_t
114tr_cpHaveValid( const tr_completion * ccp )
115{
116    if( ccp->haveValidIsDirty )
117    {
118        tr_piece_index_t i;
119        uint64_t size = 0;
120        tr_completion * cp = (tr_completion *) ccp; /* mutable */
121        const tr_torrent * tor = ccp->tor;
122        const tr_info * info = &tor->info;
123
124        for( i=0; i<info->pieceCount; ++i )
125            if( tr_cpPieceIsComplete( ccp, i ) )
126                size += tr_torPieceCountBytes( tor, i );
127
128        cp->haveValidLazy = size;
129        cp->haveValidIsDirty = false;
130    }
131
132    return ccp->haveValidLazy;
133}
134
135uint64_t
136tr_cpSizeWhenDone( const tr_completion * ccp )
137{
138    if( ccp->sizeWhenDoneIsDirty )
139    {
140        uint64_t size = 0;
141        const tr_torrent * tor = ccp->tor;
142        tr_completion * cp = (tr_completion *) ccp; /* mutable */
143
144        if( tr_cpHasAll( ccp ) )
145        {
146            size = tor->info.totalSize;
147        }
148        else
149        {
150            tr_piece_index_t p;
151
152            for( p=0; p<tor->info.pieceCount; ++p )
153            {
154                if( !tor->info.pieces[p].dnd )
155                {
156                    size += tr_torPieceCountBytes( tor, p );
157                }
158                else
159                {
160                    tr_block_index_t b, f, l;
161                    tr_torGetPieceBlockRange( cp->tor, p, &f, &l );
162                    for( b=f; b<=l; ++b )
163                        if( tr_cpBlockIsComplete( cp, b ) )
164                            size += tr_torBlockCountBytes( tor, b );
165                }
166            }
167        }
168
169        cp->sizeWhenDoneLazy = size;
170        cp->sizeWhenDoneIsDirty = false;
171    }
172
173    return ccp->sizeWhenDoneLazy;
174}
175
176void
177tr_cpGetAmountDone( const tr_completion * cp, float * tab, int tabCount )
178{
179    int i;
180    const bool seed = tr_cpHasAll( cp );
181    const float interval = cp->tor->info.pieceCount / (float)tabCount;
182
183    for( i=0; i<tabCount; ++i ) {
184        if( seed )
185            tab[i] = 1.0f;
186        else {
187            tr_block_index_t f, l;
188            const tr_piece_index_t piece = (tr_piece_index_t)i * interval;
189            tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
190            tab[i] = tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 )
191                                                            / (float)(l+1-f);
192        }
193    }
194}
195
196size_t
197tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
198{
199    if( tr_cpHasAll( cp ) )
200        return 0;
201    else {
202        tr_block_index_t f, l;
203        tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
204        return (l+1-f) - tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 );
205    }
206}
207
208size_t
209tr_cpMissingBytesInPiece( const tr_completion * cp, tr_piece_index_t piece )
210{
211    if( tr_cpHasAll( cp ) )
212        return 0;
213    else {
214        size_t haveBytes = 0;
215        tr_block_index_t f, l;
216        tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
217        haveBytes = tr_bitfieldCountRange( &cp->blockBitfield, f, l );
218        haveBytes *= cp->tor->blockSize;
219        if( tr_bitfieldHas( &cp->blockBitfield, l ) )
220            haveBytes += tr_torBlockCountBytes( cp->tor, l );
221        return tr_torPieceCountBytes( cp->tor, piece ) - haveBytes;
222    }
223}
224
225bool
226tr_cpFileIsComplete( const tr_completion * cp, tr_file_index_t i )
227{
228    if( cp->tor->info.files[i].length == 0 )
229        return true;
230    else {
231        tr_block_index_t f, l;
232        tr_torGetFileBlockRange( cp->tor, i, &f, &l );
233        return tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 ) == (l+1-f);
234    }
235}
236
237void *
238tr_cpCreatePieceBitfield( const tr_completion * cp, size_t * byte_count )
239{
240    void * ret;
241    tr_bitfield pieces;
242    const tr_piece_index_t n = cp->tor->info.pieceCount;
243    tr_bitfieldConstruct( &pieces, n );
244
245    if( tr_cpHasAll( cp ) )
246        tr_bitfieldSetHasAll( &pieces );
247    else if( !tr_cpHasNone( cp ) ) {
248        tr_piece_index_t i;
249        for( i=0; i<n; ++i )
250            if( tr_cpPieceIsComplete( cp, i ) )
251                tr_bitfieldAdd( &pieces, i );
252    }
253
254    ret = tr_bitfieldGetRaw( &pieces, byte_count );
255    tr_bitfieldDestruct( &pieces );
256    return ret;
257}
258
259double
260tr_cpPercentComplete( const tr_completion * cp )
261{
262    const double ratio = tr_getRatio( cp->sizeNow, cp->tor->info.totalSize );
263
264    if( (int)ratio == TR_RATIO_NA )
265        return 0.0;
266    else if( (int)ratio == TR_RATIO_INF )
267        return 1.0;
268    else
269        return ratio;
270}
271
272double
273tr_cpPercentDone( const tr_completion * cp )
274{
275    const double ratio = tr_getRatio( cp->sizeNow, tr_cpSizeWhenDone( cp ) );
276    const int iratio = (int)ratio;
277    return ((iratio == TR_RATIO_NA) || (iratio == TR_RATIO_INF)) ? 0.0 : ratio;
278}
Note: See TracBrowser for help on using the repository browser.