source: trunk/libtransmission/completion.c @ 12251

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

(trunk libT) more completion and bitfield cleanup: (1) fix regression in tr_cpSizeWhenDone() reported by Waldorf, (2) make simple one-liner functions inlined

  • Property svn:keywords set to Date Rev Author Id
File size: 7.1 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 12251 2011-03-29 01:17:18Z 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
39bool
40tr_cpBlockInit( tr_completion * cp, const tr_bitfield * b )
41{
42    bool success;
43
44    tr_cpReset( cp );
45
46    /* set blockBitfield */
47    success = tr_bitfieldSetFromBitfield( &cp->blockBitfield, b );
48
49    /* set sizeNow */
50    cp->sizeNow = tr_bitfieldCountTrueBits( &cp->blockBitfield );
51    cp->sizeNow *= cp->tor->blockSize;
52    if( tr_bitfieldHas( b, cp->tor->blockCount-1 ) )
53        cp->sizeNow -= ( cp->tor->blockSize - cp->tor->lastBlockSize );
54
55    return success;
56}
57
58/***
59****
60***/
61
62tr_completeness
63tr_cpGetStatus( const tr_completion * cp )
64{
65    if( tr_cpHasAll( cp ) ) return TR_SEED;
66    if( !tr_torrentHasMetadata( cp->tor ) ) return TR_LEECH;
67    if( cp->sizeNow == tr_cpSizeWhenDone( cp ) ) return TR_PARTIAL_SEED;
68    return TR_LEECH;
69}
70
71void
72tr_cpPieceRem( tr_completion *  cp, tr_piece_index_t piece )
73{
74    tr_block_index_t i, f, l;
75    const tr_torrent * tor = cp->tor;
76
77    tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
78
79    for( i=f; i<=l; ++i )
80        if( tr_cpBlockIsComplete( cp, i ) )
81            cp->sizeNow -= tr_torBlockCountBytes( tor, i );
82
83    cp->haveValidIsDirty = true;
84    cp->sizeWhenDoneIsDirty = true;
85    tr_bitfieldRemRange( &cp->blockBitfield, f, l+1 );
86}
87
88void
89tr_cpPieceAdd( tr_completion * cp, tr_piece_index_t piece )
90{
91    tr_block_index_t i, f, l;
92    tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
93
94    for( i=f; i<=l; ++i )
95        tr_cpBlockAdd( cp, i );
96}
97
98void
99tr_cpBlockAdd( tr_completion * cp, tr_block_index_t block )
100{
101    const tr_torrent * tor = cp->tor;
102
103    if( !tr_cpBlockIsComplete( cp, block ) )
104    {
105        tr_bitfieldAdd( &cp->blockBitfield, block );
106        cp->sizeNow += tr_torBlockCountBytes( tor, block );
107
108        cp->haveValidIsDirty = true;
109        cp->sizeWhenDoneIsDirty = true;
110    }
111}
112
113/***
114****
115***/
116
117uint64_t
118tr_cpHaveValid( const tr_completion * ccp )
119{
120    if( ccp->haveValidIsDirty )
121    {
122        tr_piece_index_t i;
123        uint64_t size = 0;
124        tr_completion * cp = (tr_completion *) ccp; /* mutable */
125        const tr_torrent * tor = ccp->tor;
126        const tr_info * info = &tor->info;
127
128        for( i=0; i<info->pieceCount; ++i )
129            if( tr_cpPieceIsComplete( ccp, i ) )
130                size += tr_torPieceCountBytes( tor, i );
131
132        cp->haveValidLazy = size;
133        cp->haveValidIsDirty = false;
134    }
135
136    return ccp->haveValidLazy;
137}
138
139uint64_t
140tr_cpSizeWhenDone( const tr_completion * ccp )
141{
142    if( ccp->sizeWhenDoneIsDirty )
143    {
144        uint64_t size = 0;
145        const tr_torrent * tor = ccp->tor;
146        tr_completion * cp = (tr_completion *) ccp; /* mutable */
147
148        if( tr_cpHasAll( ccp ) )
149        {
150            size = tor->info.totalSize;
151        }
152        else
153        {
154            tr_piece_index_t p;
155
156            for( p=0; p<tor->info.pieceCount; ++p )
157            {
158                if( !tor->info.pieces[p].dnd )
159                {
160                    size += tr_torPieceCountBytes( tor, p );
161                }
162                else
163                {
164                    tr_block_index_t b, f, l;
165                    tr_torGetPieceBlockRange( cp->tor, p, &f, &l );
166                    for( b=f; b<=l; ++b )
167                        if( tr_cpBlockIsComplete( cp, b ) )
168                            size += tr_torBlockCountBytes( tor, b );
169                }
170            }
171        }
172
173        cp->sizeWhenDoneLazy = size;
174        cp->sizeWhenDoneIsDirty = false;
175    }
176
177    return ccp->sizeWhenDoneLazy;
178}
179
180void
181tr_cpGetAmountDone( const tr_completion * cp, float * tab, int tabCount )
182{
183    int i;
184    const bool seed = tr_cpHasAll( cp );
185    const float interval = cp->tor->info.pieceCount / (float)tabCount;
186
187    for( i=0; i<tabCount; ++i ) {
188        if( seed )
189            tab[i] = 1.0f;
190        else {
191            tr_block_index_t f, l;
192            const tr_piece_index_t piece = (tr_piece_index_t)i * interval;
193            tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
194            tab[i] = tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 )
195                                                            / (float)(l+1-f);
196        }
197    }
198}
199
200size_t
201tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
202{
203    if( tr_cpHasAll( cp ) )
204        return 0;
205    else {
206        tr_block_index_t f, l;
207        tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
208        return (l+1-f) - tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 );
209    }
210}
211
212size_t
213tr_cpMissingBytesInPiece( const tr_completion * cp, tr_piece_index_t piece )
214{
215    if( tr_cpHasAll( cp ) )
216        return 0;
217    else {
218        size_t haveBytes = 0;
219        tr_block_index_t f, l;
220        tr_torGetPieceBlockRange( cp->tor, piece, &f, &l );
221        haveBytes = tr_bitfieldCountRange( &cp->blockBitfield, f, l );
222        haveBytes *= cp->tor->blockSize;
223        if( tr_bitfieldHas( &cp->blockBitfield, l ) )
224            haveBytes += tr_torBlockCountBytes( cp->tor, l );
225        return tr_torPieceCountBytes( cp->tor, piece ) - haveBytes;
226    }
227}
228
229bool
230tr_cpFileIsComplete( const tr_completion * cp, tr_file_index_t i )
231{
232    if( cp->tor->info.files[i].length == 0 )
233        return true;
234    else {
235        tr_block_index_t f, l;
236        tr_torGetFileBlockRange( cp->tor, i, &f, &l );
237        return tr_bitfieldCountRange( &cp->blockBitfield, f, l+1 ) == (l+1-f);
238    }
239}
240
241void *
242tr_cpCreatePieceBitfield( const tr_completion * cp, size_t * byte_count )
243{
244    void * ret;
245    tr_bitfield pieces;
246    const tr_piece_index_t n = cp->tor->info.pieceCount;
247    tr_bitfieldConstruct( &pieces, n );
248
249    if( tr_cpHasAll( cp ) )
250        tr_bitfieldSetHasAll( &pieces );
251    else if( !tr_cpHasNone( cp ) ) {
252        tr_piece_index_t i;
253        for( i=0; i<n; ++i )
254            if( tr_cpPieceIsComplete( cp, i ) )
255                tr_bitfieldAdd( &pieces, i );
256    }
257
258    ret = tr_bitfieldGetRaw( &pieces, byte_count );
259    tr_bitfieldDestruct( &pieces );
260    return ret;
261}
262
263double
264tr_cpPercentComplete( const tr_completion * cp )
265{
266    const double ratio = tr_getRatio( cp->sizeNow, cp->tor->info.totalSize );
267
268    if( (int)ratio == TR_RATIO_NA )
269        return 0.0;
270    else if( (int)ratio == TR_RATIO_INF )
271        return 1.0;
272    else
273        return ratio;
274}
275
276double
277tr_cpPercentDone( const tr_completion * cp )
278{
279    const double ratio = tr_getRatio( cp->sizeNow, tr_cpSizeWhenDone( cp ) );
280    const int iratio = (int)ratio;
281    return ((iratio == TR_RATIO_NA) || (iratio == TR_RATIO_INF)) ? 0.0 : ratio;
282}
Note: See TracBrowser for help on using the repository browser.