source: trunk/libtransmission/completion.c @ 12515

Last change on this file since 12515 was 12515, checked in by jordan, 10 years ago

(trunk libT) #4332 "countRange/countArray exception" -- fix bug in tr_cpMissingBytesInPiece()

  • 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 12515 2011-06-25 13:31:25Z 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+1 );
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.