source: trunk/libtransmission/verify.c @ 5208

Last change on this file since 5208 was 5208, checked in by charles, 14 years ago

more i18n strings work

  • Property svn:keywords set to Date Rev Author Id
File size: 5.1 KB
Line 
1/*
2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
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: verify.c 5208 2008-03-06 21:59:00Z charles $
11 */
12
13#include <sys/stat.h>
14
15#include "transmission.h"
16#include "completion.h"
17#include "fastresume.h" /* tr_fastResumeSave() */
18#include "inout.h"
19#include "list.h"
20#include "platform.h"
21#include "torrent.h"
22#include "utils.h" /* tr_buildPath */
23#include "verify.h"
24
25/**
26***
27**/
28
29struct verify_node
30{
31    tr_torrent * torrent;
32    tr_verify_done_cb verify_done_cb;
33};
34
35static void
36fireCheckDone( tr_torrent          * torrent,
37               tr_verify_done_cb    verify_done_cb )
38{
39    if( verify_done_cb != NULL )
40        (*verify_done_cb)( torrent );
41}
42
43static struct verify_node currentNode;
44
45static tr_list * verifyList = NULL;
46
47static tr_thread * verifyThread = NULL;
48
49static int stopCurrent = FALSE;
50
51static tr_lock* getVerifyLock( void )
52{
53    static tr_lock * lock = NULL;
54    if( lock == NULL )
55        lock = tr_lockNew( );
56    return lock;
57}
58
59static void
60checkFile( tr_torrent   * tor,
61           int            fileIndex,
62           int          * abortFlag )
63{
64    int i;
65    int nofile;
66    struct stat sb;
67    char path[MAX_PATH_LENGTH];
68    const tr_file * file = &tor->info.files[fileIndex];
69
70    tr_buildPath ( path, sizeof(path), tor->destination, file->name, NULL );
71    nofile = stat( path, &sb ) || !S_ISREG( sb.st_mode );
72
73    for( i=file->firstPiece; i<=file->lastPiece && i<tor->info.pieceCount && (!*abortFlag); ++i )
74    {
75        if( nofile )
76        {
77            tr_torrentSetHasPiece( tor, i, 0 );
78        }
79        else if( !tr_torrentIsPieceChecked( tor, i ) )
80        {
81            const tr_errno err = tr_ioTestPiece( tor, i );
82
83            if( !err ) /* yay */
84            {
85                tr_torrentSetHasPiece( tor, i, TRUE );
86            }
87            else
88            {
89                /* if we were wrong about it being complete,
90                 * reset and start again.  if we were right about
91                 * it being incomplete, do nothing -- we don't
92                 * want to lose blocks in those incomplete pieces */
93
94                if( tr_cpPieceIsComplete( tor->completion, i ) )
95                    tr_torrentSetHasPiece( tor, i, FALSE );
96            }
97        }
98
99        tr_torrentSetPieceChecked( tor, i, TRUE );
100    }
101}
102
103static void
104verifyThreadFunc( void * unused UNUSED )
105{
106    for( ;; )
107    {
108        int i;
109        tr_torrent * tor;
110        struct verify_node * node;
111
112        tr_lockLock( getVerifyLock( ) );
113        stopCurrent = FALSE;
114        node = (struct verify_node*) verifyList ? verifyList->data : NULL;
115        if( node == NULL ) {
116            currentNode.torrent = NULL;
117            break;
118        }
119
120        currentNode = *node;
121        tor = currentNode.torrent;
122        tr_list_remove_data( &verifyList, node );
123        tr_free( node );
124        tr_lockUnlock( getVerifyLock( ) );
125
126        tor->verifyState = TR_VERIFY_NOW;
127
128        tr_inf( _( "Verifying some pieces of \"%s\"" ), tor->info.name );
129        for( i=0; i<tor->info.fileCount && !stopCurrent; ++i )
130            checkFile( tor, i, &stopCurrent );
131
132        tor->verifyState = TR_VERIFY_NONE;
133
134        if( !stopCurrent )
135        {
136            tr_fastResumeSave( tor );
137            fireCheckDone( tor, currentNode.verify_done_cb );
138        }
139    }
140
141    verifyThread = NULL;
142    tr_lockUnlock( getVerifyLock( ) );
143}
144
145void
146tr_verifyAdd( tr_torrent          * tor,
147              tr_verify_done_cb    verify_done_cb )
148{
149    const int uncheckedCount = tr_torrentCountUncheckedPieces( tor );
150
151    if( !uncheckedCount )
152    {
153        /* doesn't need to be checked... */
154        verify_done_cb( tor );
155    }
156    else
157    {
158        struct verify_node * node;
159
160        tr_inf( _( "Queueing \"%s\" for verification" ), tor->info.name );
161
162        node = tr_new( struct verify_node, 1 );
163        node->torrent = tor;
164        node->verify_done_cb = verify_done_cb;
165
166        tr_lockLock( getVerifyLock( ) );
167        tor->verifyState = verifyList ? TR_VERIFY_WAIT : TR_VERIFY_NOW;
168        tr_list_append( &verifyList, node );
169        if( verifyThread == NULL )
170            verifyThread = tr_threadNew( verifyThreadFunc, NULL, "verifyThreadFunc" );
171        tr_lockUnlock( getVerifyLock( ) );
172    }
173}
174
175static int
176compareVerifyByTorrent( const void * va, const void * vb )
177{
178    const struct verify_node * a = va;
179    const tr_torrent * b = vb;
180    return a->torrent - b;
181}
182
183void
184tr_verifyRemove( tr_torrent * tor )
185{
186    tr_lock * lock = getVerifyLock( );
187    tr_lockLock( lock );
188
189    if( tor == currentNode.torrent )
190    {
191        stopCurrent = TRUE;
192        while( stopCurrent )
193        {
194            tr_lockUnlock( lock );
195            tr_wait( 100 );
196            tr_lockLock( lock );
197        }
198    }
199    else
200    {
201        tr_free( tr_list_remove( &verifyList, tor, compareVerifyByTorrent ) );
202        tor->verifyState = TR_VERIFY_NONE;
203    }
204
205    tr_lockUnlock( lock );
206}
Note: See TracBrowser for help on using the repository browser.