Mercurial > noffle
view src/expire.c @ 439:e97ef1e08970 noffle
[svn] * NEWS: Update for 1.1.5.
author | bears |
---|---|
date | Wed, 25 Jun 2003 10:55:16 +0100 |
parents | 52f467c7213b |
children |
line wrap: on
line source
/* expire.c $Id: expire.c 387 2002-06-26 13:15:44Z bears $ Handle expiring articles from the article base. */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include "configfile.h" #include "content.h" #include "database.h" #include "expire.h" #include "fetchlist.h" #include "group.h" #include "itemlist.h" #include "log.h" #include "protocol.h" #include "pseudo.h" #include "util.h" #include "portable.h" /* * Find the maximum expire time in days for this article. * Different groups may have different limits, so we need to * check the limit for each group. */ static int calcExpireDays( const char *msgId ) { const char *xref; ItemList *refs; const char *ref; int res; xref = Db_xref( msgId ); if ( xref[ 0 ] == '\0' ) return -1; res = -1; refs = new_Itl( xref, " :" ); for ( ref = Itl_first( refs ); ref != NULL; ref = Itl_next( refs ) ) { int days; days = Cfg_expire( ref ); if ( days == 0 || ( days > res && res != 0 ) ) res = days; Itl_next( refs ); /* Throw away group number */ } del_Itl( refs ); return res; } /* Does this article need to be expired? */ static Bool articleExpired( const char *msgId, time_t now ) { int expDays; time_t lastAccess; Str expires; time_t texpires; expDays = calcExpireDays( msgId ); if ( expDays == -1 ) { Log_err( "Internal error: Failed expiry calculation on %s", msgId ); return TRUE; } lastAccess = Db_lastAccess( msgId ); if ( lastAccess == -1 ) { Log_err( "Internal error: Getting lastAccess of %s failed", msgId ); return TRUE; } if ( Prt_searchHeader( Db_header( msgId ), "Expires", expires ) ) texpires = Utl_parseNewsDate( expires ); else texpires = (time_t) -1; if ( expDays > 0 && difftime( now, lastAccess ) > ( (double) expDays * 24 * 3600 ) ) { #ifdef DEBUG Str lastStr, nowStr; Utl_cpyStr( lastStr, ctime( &lastAccess ) ); lastStr[ strlen( lastStr ) - 1 ] = '\0'; Utl_cpyStr( nowStr, ctime( &now ) ); nowStr[ strlen( nowStr ) - 1 ] = '\0'; Log_dbg( LOG_DBG_EXPIRE, "Expiring %s: last access %s, time now %s", msgId, lastStr, nowStr ); #endif } else if ( ( texpires != (time_t) -1 ) && now > texpires ) { Log_dbg( LOG_DBG_EXPIRE, "Expiring %s: Expires header activated", msgId ); } else return FALSE; return TRUE; } /* Work though all overviews looking for articles to expire. */ void Exp_expire( void ) { const Over *ov; int i; int cntDel, cntLeft; Str grp; Bool autoUnsubscribe; int autoUnsubscribeDays; time_t now, maxAge = 0; const char *msgId; autoUnsubscribe = Cfg_autoUnsubscribe(); autoUnsubscribeDays = Cfg_autoUnsubscribeDays(); maxAge = Cfg_autoUnsubscribeDays() * 24 * 3600; if ( ! Cont_firstGrp( grp ) ) return; Log_inf( "Expiring articles" ); Fetchlist_read(); now = time( NULL ); do { if ( ! Grp_exists( grp ) ) Log_err( "Overview file for unknown group %s exists", grp ); else { cntDel = cntLeft = 0; Cont_read( grp ); for ( i = Cont_first(); i <= Cont_last(); ++i ) { if ( ! Cont_validNumb( i ) ) continue; if ( ( ov = Cont_get( i ) ) ) { msgId = Ov_msgId( ov ); /* Crossposted articles may have already been deleted. */ if ( ! Db_contains( msgId ) ) { Cont_delete( i ); ++cntDel; } else if ( articleExpired( msgId, now ) ) { Cont_delete( i ); Db_delete( msgId ); ++cntDel; } else ++cntLeft; } } /* * Auto unsubscribe where applicable if last article arrival * time is maxAge newer than the last access time. This ensures * the low traffic groups don't get expired simply because * there's been nothing to read. */ if ( ! Grp_local( grp ) && Fetchlist_contains( grp, NULL ) && autoUnsubscribe && difftime( Grp_lastPostTime(grp), Grp_lastAccess( grp ) ) > maxAge ) { Log_ntc( "Auto-unsubscribing from %s after %d " "days without access", grp, autoUnsubscribeDays ); Pseudo_autoUnsubscribed( grp, autoUnsubscribeDays ); Fetchlist_remove( grp ); Grp_setRmtNext( grp, GRP_RMT_NEXT_NOT_SUBSCRIBED ); } if ( Cont_write() ) Grp_setFirstLast( grp, Cont_first(), Cont_last() ); Log_inf( "%ld overviews deleted from group %s, %ld left (%ld-%ld)", cntDel, grp, cntLeft, Grp_first( grp ), Grp_last( grp ) ); } } while ( Cont_nextGrp( grp ) ); Fetchlist_write(); Db_compact(); }