comparison src/fetch.c @ 188:f1bacee93ca6 noffle

[svn] * src/client.c,src/client.h,src/fetch.c,src/noffle.c,src/server.c: robustness - instead of retruning simple Passed/Failed statuses from connection functions, return an integer status instead. This allows Noffle to distinguish between a connection failure, an unrecoverable protocol error and a recoverable problem. As a concrete instance, Noffle will no longer abort the connection if a group is removed from the upstream server. Also beef up error detection a bit. * src/content.c: instead of overwriting the existing content file(s) when updating - which leaves a window where Noffle is vulnerable to failure which will leave the content file corrupted (yes, it happened to me), write a new content file and rename it over the old file only when it has been written and closed with no errors reported.
author bears
date Wed, 12 Sep 2001 21:33:44 +0100
parents fed1334d766b
children 021d145e34e9
comparison
equal deleted inserted replaced
187:166008a80f03 188:f1bacee93ca6
1 /* 1 /*
2 fetch.c 2 fetch.c
3 3
4 $Id: fetch.c 300 2001-08-05 08:24:22Z bears $ 4 $Id: fetch.c 307 2001-09-12 20:33:44Z bears $
5 */ 5 */
6 6
7 #if HAVE_CONFIG_H 7 #if HAVE_CONFIG_H
8 #include <config.h> 8 #include <config.h>
9 #endif 9 #endif
72 { 72 {
73 Log_err( "Cannot read %s. Please run noffle --query groups", file ); 73 Log_err( "Cannot read %s. Please run noffle --query groups", file );
74 return FALSE; 74 return FALSE;
75 } 75 }
76 Log_inf( "Updating groupinfo" ); 76 Log_inf( "Updating groupinfo" );
77 return Client_getNewgrps( &t ); 77
78 /*
79 * If NEWGROUPS fails, it isn't necessarily fatal. You can do
80 * a periodic noffle --query groups to refresh your group list.
81 * So only return failure here if the status indicates the link
82 * itself failed.
83 *
84 * In particular, older versions of NNTPcache have a Y2K bug that
85 * stops NEWGROUPS working.
86 */
87 return ( ! IS_FATAL( Client_getNewgrps( &t ) ) );
78 } 88 }
79 89
80 /* Databases open on entry, closed on exit. */ 90 /* Databases open on entry, closed on exit. */
81 static Bool 91 static int
82 fetchNewArts( const char *name, FetchMode mode ) 92 fetchNewArts( const char *name, FetchMode mode )
83 { 93 {
84 int next, first, last, refetch; 94 int next, first, last, refetch, stat;
85 95
86 if ( ! Client_changeToGrp( name ) ) 96 stat = Client_changeToGrp( name );
97 if ( stat != STAT_OK )
87 { 98 {
88 Log_err( "Could not change to group %s", name ); 99 Log_err( "Could not change to group %s", name );
89 if ( Lock_gotLock() ) 100 if ( Lock_gotLock() )
90 Lock_closeDatabases(); 101 Lock_closeDatabases();
91 return TRUE; 102 return stat;
92 } 103 }
93 Client_rmtFirstLast( &first, &last ); 104 Client_rmtFirstLast( &first, &last );
94 Cont_read( name ); 105 Cont_read( name );
95 next = Grp_rmtNext( name ); 106 next = Grp_rmtNext( name );
96 if ( next == GRP_RMT_NEXT_NOT_SUBSCRIBED ) 107 if ( next == GRP_RMT_NEXT_NOT_SUBSCRIBED )
99 { 110 {
100 Log_inf( "No new articles in %s", name ); 111 Log_inf( "No new articles in %s", name );
101 Cont_write(); 112 Cont_write();
102 Grp_setFirstLast( name, Cont_first(), Cont_last() ); 113 Grp_setFirstLast( name, Cont_first(), Cont_last() );
103 Lock_closeDatabases(); 114 Lock_closeDatabases();
104 return TRUE; 115 return STAT_OK;
105 } 116 }
106 if ( first == 0 && last == 0 ) 117 if ( first == 0 && last == 0 )
107 { 118 {
108 Log_inf( "No articles in %s", name ); 119 Log_inf( "No articles in %s", name );
109 Cont_write(); 120 Cont_write();
110 Grp_setFirstLast( name, Cont_first(), Cont_last() ); 121 Grp_setFirstLast( name, Cont_first(), Cont_last() );
111 Lock_closeDatabases(); 122 Lock_closeDatabases();
112 return TRUE; 123 return STAT_OK;
113 } 124 }
114 if ( next > last + 1 ) 125 if ( next > last + 1 )
115 { 126 {
116 refetch = last - Cfg_maxFetch() + 1; 127 refetch = last - Cfg_maxFetch() + 1;
117 if ( refetch < 0 ) refetch = 1; 128 if ( refetch < 0 ) refetch = 1;
118 Log_err( "Article number inconsistent (%s rmt=%lu-%lu, next=%lu). Refetching from %lu", 129 Log_err( "Article number inconsistent (%s rmt=%lu-%lu, next=%lu). "
130 "Refetching from %lu",
119 name, first, last, next, refetch ); 131 name, first, last, next, refetch );
120 Pseudo_cntInconsistent( name, first, last, next, refetch ); 132 Pseudo_cntInconsistent( name, first, last, next, refetch );
121 first = refetch; 133 first = refetch;
122 } 134 }
123 else if ( next < first ) 135 else if ( next < first )
124 { 136 {
125 Log_inf( "Missing articles (%s first=%lu next=%lu)", 137 Log_inf( "Missing articles (%s first=%lu next=%lu)",
126 name, first, next ); 138 name, first, next );
127 Pseudo_missArts( name, first, next ); 139 Pseudo_missArts( name, first, next );
140
141 /*
142 * If we are missing articles but there are none to fetch,
143 * we must ensure we don't repeatedly generate missing
144 * article warning on every fetch until there is something
145 * to fetch. To guard against this, update the group remote
146 * next now.
147 */
148 Grp_setRmtNext( name, first );
149 next = first;
128 } 150 }
129 else 151 else
130 first = next; 152 first = next;
131 if ( last - first > Cfg_maxFetch() ) 153 if ( last - first > Cfg_maxFetch() )
132 { 154 {
168 for ( i = 0; i < size; ++i ) 190 for ( i = 0; i < size; ++i )
169 { 191 {
170 Fetchlist_element( &name, &mode, i ); 192 Fetchlist_element( &name, &mode, i );
171 if ( strcmp( Grp_server( name ), fetch.serv ) == 0 ) 193 if ( strcmp( Grp_server( name ), fetch.serv ) == 0 )
172 { 194 {
173 if ( ! fetchNewArts( name, mode ) ) 195 if ( IS_FATAL( fetchNewArts( name, mode ) ) )
174 return FALSE; 196 return FALSE;
175 if ( ! Lock_openDatabases() ) 197 if ( ! Lock_openDatabases() )
176 { 198 {
177 Log_err( "Could not open message base" ); 199 Log_err( "Could not open message base" );
178 return FALSE; 200 return FALSE;
181 } 203 }
182 Lock_closeDatabases(); 204 Lock_closeDatabases();
183 return TRUE; 205 return TRUE;
184 } 206 }
185 207
186 static Bool 208 static int
187 fetchMessageList( const char *list, int *artcnt, int artmax ) 209 fetchMessageList( const char *list, int *artcnt, int artmax )
188 { 210 {
189 const char *p; 211 const char *p;
190 Str msgId; 212 Str msgId;
213 int stat;
191 214
192 ASSERT( Lock_gotLock() ); 215 ASSERT( Lock_gotLock() );
193 if ( ! Client_retrieveArtList( list, artcnt, artmax ) ) 216 stat = Client_retrieveArtList( list, artcnt, artmax );
194 return FALSE; 217 if ( stat != STAT_OK )
218 return stat;
195 p = list; 219 p = list;
196 while ( ( p = Utl_getLn( msgId, p ) ) ) 220 while ( ( p = Utl_getLn( msgId, p ) ) )
197 Req_remove( fetch.serv, msgId ); 221 Req_remove( fetch.serv, msgId );
198 return TRUE; 222 return STAT_OK;
199 } 223 }
200 224
201 Bool 225 Bool
202 Fetch_getReq_( void ) 226 Fetch_getReq_( void )
203 { 227 {
205 DynStr *list; 229 DynStr *list;
206 DynStr *fetchList; 230 DynStr *fetchList;
207 const char *p; 231 const char *p;
208 int count = 0, artcnt = 0, artmax = 0; 232 int count = 0, artcnt = 0, artmax = 0;
209 Bool res; 233 Bool res;
234 int stat;
210 235
211 ASSERT( fetch.ready ); 236 ASSERT( fetch.ready );
212 Log_dbg( LOG_DBG_FETCH, "Retrieving articles marked for download" ); 237 Log_dbg( LOG_DBG_FETCH, "Retrieving articles marked for download" );
213 list = new_DynStr( 10000 ); 238 list = new_DynStr( 10000 );
214 fetchList = new_DynStr( 1000 ); 239 fetchList = new_DynStr( 1000 );
248 while ( res && ( p = Utl_getLn( msgId, p ) ) != NULL ) 273 while ( res && ( p = Utl_getLn( msgId, p ) ) != NULL )
249 { 274 {
250 DynStr_appLn( fetchList, msgId ); 275 DynStr_appLn( fetchList, msgId );
251 if ( ++count % MAX_ARTICLE_CMDS_QUEUED == 0 ) 276 if ( ++count % MAX_ARTICLE_CMDS_QUEUED == 0 )
252 { 277 {
253 res = fetchMessageList( DynStr_str( fetchList ), &artcnt, artmax ); 278 stat = fetchMessageList( DynStr_str( fetchList ), &artcnt,
279 artmax );
280 res = ! IS_FATAL( stat );
254 DynStr_clear( fetchList ); 281 DynStr_clear( fetchList );
255 } 282 }
256 } 283 }
257 res = res && fetchMessageList( DynStr_str( fetchList ), &artcnt, artmax ); 284 stat = fetchMessageList( DynStr_str( fetchList ), &artcnt, artmax );
285 res = res && ! IS_FATAL( stat );
258 286
259 del_DynStr( fetchList ); 287 del_DynStr( fetchList );
260 del_DynStr( list ); 288 del_DynStr( list );
261 Lock_closeDatabases(); 289 Lock_closeDatabases();
262 return res; 290 return res;
317 { 345 {
318 Log_inf( "Posting articles" ); 346 Log_inf( "Posting articles" );
319 do 347 do
320 { 348 {
321 txt = DynStr_str( s ); 349 txt = DynStr_str( s );
322 if ( ! Client_postArt( msgId, txt, errStr ) ) 350 if ( Client_postArt( msgId, txt, errStr ) != STAT_OK )
323 { 351 {
324 res = FALSE; 352 res = FALSE;
325 break; 353 break;
326 } 354 }
327 355