@ -145,7 +145,7 @@ typedef struct {
channel_conf_t * chan ;
store_t * ctx [ 2 ] ;
driver_t * drv [ 2 ] ;
int state [ 2 ] , ret ;
int state [ 2 ] , ref_count , re t ;
int find_old_total [ 2 ] , find_old_done [ 2 ] ;
int new_total [ 2 ] , new_done [ 2 ] ;
int find_new_total [ 2 ] , find_new_done [ 2 ] ;
@ -155,6 +155,26 @@ typedef struct {
unsigned find : 1 ;
} sync_vars_t ;
static void sync_ref ( sync_vars_t * svars ) { + + svars - > ref_count ; }
static int sync_deref ( sync_vars_t * svars ) ;
static int deref_check_cancel ( sync_vars_t * svars ) ;
static int check_cancel ( sync_vars_t * svars ) ;
# define DRIVER_CALL_RET(call) \
do { \
sync_ref ( svars ) ; \
svars - > drv [ t ] - > call ; \
return deref_check_cancel ( svars ) ; \
} while ( 0 )
# define DRIVER_CALL(call) \
do { \
sync_ref ( svars ) ; \
svars - > drv [ t ] - > call ; \
if ( deref_check_cancel ( svars ) ) \
return ; \
} while ( 0 )
# define AUX &svars->t[t]
# define DECL_SVARS \
int t ; \
@ -192,27 +212,28 @@ typedef struct {
typedef struct copy_vars {
int ( * cb ) ( int sts , int uid , struct copy_vars * vars ) ;
void ( * cb ) ( int sts , int uid , struct copy_vars * vars ) ;
void * aux ;
sync_rec_t * srec ; /* also ->tuid */
message_t * msg ;
msg_data_t data ;
} copy_vars_t ;
static int msg_fetched ( int sts , void * aux ) ;
static void msg_fetched ( int sts , void * aux ) ;
static int
copy_msg ( copy_vars_t * vars )
{
DECL_INIT_SVARS ( vars - > aux ) ;
t ^ = 1 ;
vars - > data . flags = vars - > msg - > flags ;
return svars - > drv [ 1 - t ] - > fetch_msg ( svars - > ctx [ 1 - t ] , vars - > msg , & vars - > data , msg_fetched , vars ) ;
DRIVER_CALL_RET ( fetch_msg ( svars - > ctx [ t ] , vars - > msg , & vars - > data , msg_fetched , vars ) ) ;
}
static int msg_stored ( int sts , int uid , void * aux ) ;
static void msg_stored ( int sts , int uid , void * aux ) ;
static int
static void
msg_fetched ( int sts , void * aux )
{
copy_vars_t * vars = ( copy_vars_t * ) aux ;
@ -260,7 +281,8 @@ msg_fetched( int sts, void *aux )
warn ( " Warning: message %d from %s has incomplete header. \n " ,
vars - > msg - > uid , str_ms [ 1 - t ] ) ;
free ( fmap ) ;
return vars - > cb ( SYNC_NOGOOD , 0 , vars ) ;
vars - > cb ( SYNC_NOGOOD , 0 , vars ) ;
return ;
oke :
extra + = 8 + TUIDL + 1 + ( tcr & & ( ! scr | | hcrs ) ) ;
}
@ -327,17 +349,21 @@ msg_fetched( int sts, void *aux )
free ( fmap ) ;
}
return svars - > drv [ t ] - > store_msg ( svars - > ctx [ t ] , & vars - > data , ! vars - > srec , msg_stored , vars ) ;
svars - > drv [ t ] - > store_msg ( svars - > ctx [ t ] , & vars - > data , ! vars - > srec , msg_stored , vars ) ;
break ;
case DRV_CANCELED :
return vars - > cb ( SYNC_CANCELED , 0 , vars ) ;
vars - > cb ( SYNC_CANCELED , 0 , vars ) ;
break ;
case DRV_MSG_BAD :
return vars - > cb ( SYNC_NOGOOD , 0 , vars ) ;
vars - > cb ( SYNC_NOGOOD , 0 , vars ) ;
break ;
default :
return vars - > cb ( SYNC_FAIL , 0 , vars ) ;
vars - > cb ( SYNC_FAIL , 0 , vars ) ;
break ;
}
}
static int
static void
msg_stored ( int sts , int uid , void * aux )
{
copy_vars_t * vars = ( copy_vars_t * ) aux ;
@ -345,17 +371,21 @@ msg_stored( int sts, int uid, void *aux )
switch ( sts ) {
case DRV_OK :
return vars - > cb ( SYNC_OK , uid , vars ) ;
vars - > cb ( SYNC_OK , uid , vars ) ;
break ;
case DRV_CANCELED :
return vars - > cb ( SYNC_CANCELED , 0 , vars ) ;
vars - > cb ( SYNC_CANCELED , 0 , vars ) ;
break ;
case DRV_MSG_BAD :
INIT_SVARS ( vars - > aux ) ;
( void ) svars ;
warn ( " Warning: %s refuses to store message %d from %s. \n " ,
str_ms [ t ] , vars - > msg - > uid , str_ms [ 1 - t ] ) ;
return vars - > cb ( SYNC_NOGOOD , 0 , vars ) ;
vars - > cb ( SYNC_NOGOOD , 0 , vars ) ;
break ;
default :
return vars - > cb ( SYNC_FAIL , 0 , vars ) ;
vars - > cb ( SYNC_FAIL , 0 , vars ) ;
break ;
}
}
@ -433,6 +463,19 @@ store_bad( void *aux )
cancel_sync ( svars ) ;
}
static int
deref_check_cancel ( sync_vars_t * svars )
{
if ( sync_deref ( svars ) )
return - 1 ;
return check_cancel ( svars ) ;
}
static int
check_cancel ( sync_vars_t * svars )
{
return ( svars - > state [ M ] | svars - > state [ S ] ) & ( ST_SENT_CANCEL | ST_CANCELED ) ;
}
static int
check_ret ( int sts , void * aux )
@ -454,7 +497,7 @@ check_ret( int sts, void *aux )
# define SVARS_CHECK_RET \
DECL_SVARS ; \
if ( check_ret ( sts , aux ) ) \
return 1 ; \
return ; \
INIT_SVARS ( aux )
# define SVARS_CHECK_RET_VARS(type) \
@ -462,7 +505,7 @@ check_ret( int sts, void *aux )
DECL_SVARS ; \
if ( check_ret ( sts , vars - > aux ) ) { \
free ( vars ) ; \
return 1 ; \
return ; \
} \
INIT_SVARS ( vars - > aux )
@ -470,7 +513,7 @@ check_ret( int sts, void *aux )
DECL_SVARS ; \
if ( sts = = SYNC_CANCELED ) { \
free ( vars ) ; \
return 1 ; \
return ; \
} \
INIT_SVARS ( vars - > aux )
@ -508,6 +551,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
svars = nfcalloc ( sizeof ( * svars ) ) ;
svars - > t [ 1 ] = 1 ;
svars - > ref_count = 1 ;
svars - > cb = cb ;
svars - > aux = aux ;
svars - > ctx [ 0 ] = ctx [ 0 ] ;
@ -830,7 +874,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
select_box ( svars , S , ( ctx [ S ] - > opts & OPEN_OLD ) ? 1 : INT_MAX , 0 , 0 ) ;
}
static int box_selected ( int sts , void * aux ) ;
static void box_selected ( int sts , void * aux ) ;
static int
select_box ( sync_vars_t * svars , int t , int minwuid , int * mexcs , int nmexcs )
@ -851,7 +895,7 @@ select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs )
maxwuid = 0 ;
info ( " Selecting %s %s... \n " , str_ms [ t ] , svars - > ctx [ t ] - > name ) ;
debug ( maxwuid = = INT_MAX ? " selecting %s [%d,inf] \n " : " selecting %s [%d,%d] \n " , str_ms [ t ] , minwuid , maxwuid ) ;
return svars - > drv [ t ] - > select ( svars - > ctx [ t ] , minwuid , maxwuid , mexcs , nmexcs , box_selected , AUX ) ;
DRIVER_CALL_RET ( select ( svars - > ctx [ t ] , minwuid , maxwuid , mexcs , nmexcs , box_selected , AUX ) ) ;
}
typedef struct {
@ -859,10 +903,10 @@ typedef struct {
sync_rec_t * srec ;
} find_vars_t ;
static int msg_found_sel ( int sts , int uid , void * aux ) ;
static int msgs_found_sel ( sync_vars_t * svars , int t ) ;
static void msg_found_sel ( int sts , int uid , void * aux ) ;
static void msgs_found_sel ( sync_vars_t * svars , int t ) ;
static int
static void
box_selected ( int sts , void * aux )
{
find_vars_t * fv ;
@ -874,7 +918,7 @@ box_selected( int sts, void *aux )
str_ms [ t ] , svars - > ctx [ t ] - > uidvalidity , svars - > uidval [ t ] ) ;
svars - > ret | = SYNC_FAIL ;
cancel_sync ( svars ) ;
return 1 ;
return ;
}
info ( " %s: %d messages, %d recent \n " , str_ms [ t ] , svars - > ctx [ t ] - > count , svars - > ctx [ t ] - > recent ) ;
@ -897,16 +941,15 @@ box_selected( int sts, void *aux )
fv = nfmalloc ( sizeof ( * fv ) ) ;
fv - > aux = AUX ;
fv - > srec = srec ;
if ( svars - > drv [ t ] - > find_msg ( svars - > ctx [ t ] , srec - > tuid , msg_found_sel , fv ) )
return 1 ;
DRIVER_CALL ( find_msg ( svars - > ctx [ t ] , srec - > tuid , msg_found_sel , fv ) ) ;
}
}
}
svars - > state [ t ] | = ST_SENT_FIND_OLD ;
return msgs_found_sel ( svars , t ) ;
msgs_found_sel ( svars , t ) ;
}
static int
static void
msg_found_sel ( int sts , int uid , void * aux )
{
SVARS_CHECK_RET_VARS ( find_vars_t ) ;
@ -927,7 +970,7 @@ msg_found_sel( int sts, int uid, void *aux )
free ( vars ) ;
svars - > find_old_done [ t ] + + ;
stats ( svars ) ;
return msgs_found_sel ( svars , t ) ;
msgs_found_sel ( svars , t ) ;
}
typedef struct {
@ -936,15 +979,15 @@ typedef struct {
int aflags , dflags ;
} flag_vars_t ;
static int flags_set_del ( int sts , void * aux ) ;
static int flags_set_sync ( int sts , void * aux ) ;
static void flags_set_del ( int sts , void * aux ) ;
static void flags_set_sync ( int sts , void * aux ) ;
static void flags_set_sync_p2 ( sync_vars_t * svars , sync_rec_t * srec , int t ) ;
static int msgs_flags_set ( sync_vars_t * svars , int t ) ;
static int msg_copied ( int sts , int uid , copy_vars_t * vars ) ;
static void msg_copied ( int sts , int uid , copy_vars_t * vars ) ;
static void msg_copied_p2 ( sync_vars_t * svars , sync_rec_t * srec , int t , message_t * tmsg , int uid ) ;
static int msgs_copied ( sync_vars_t * svars , int t ) ;
static void msgs_copied ( sync_vars_t * svars , int t ) ;
static int
static void
msgs_found_sel ( sync_vars_t * svars , int t )
{
sync_rec_t * srec , * nsrec = 0 ;
@ -957,7 +1000,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
char fbuf [ 16 ] ; /* enlarge when support for keywords is added */
if ( ! ( svars - > state [ t ] & ST_SENT_FIND_OLD ) | | svars - > find_old_done [ t ] < svars - > find_old_total [ t ] )
return 0 ;
return ;
/*
* Mapping tmsg - > srec ( this variant ) is dog slow for new messages .
@ -1053,11 +1096,12 @@ msgs_found_sel( sync_vars_t *svars, int t )
for ( t = 0 ; t < nmexcs ; t + + )
debugn ( " %d " , mexcs [ t ] ) ;
debug ( " \n " ) ;
return select_box ( svars , M , minwuid , mexcs , nmexcs ) ;
select_box ( svars , M , minwuid , mexcs , nmexcs ) ;
return ;
}
if ( ! ( svars - > state [ 1 - t ] & ST_SENT_FIND_OLD ) | | svars - > find_old_done [ 1 - t ] < svars - > find_old_total [ 1 - t ] )
return 0 ;
return ;
if ( svars - > uidval [ M ] < 0 | | svars - > uidval [ S ] < 0 ) {
svars - > uidval [ M ] = svars - > ctx [ M ] - > uidvalidity ;
@ -1113,7 +1157,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
Fprintf ( svars - > jfp , " # %d %d %. " stringify ( TUIDL ) " s \n " , srec - > uid [ M ] , srec - > uid [ S ] , srec - > tuid ) ;
debug ( " -> %sing message, TUID %. " stringify ( TUIDL ) " s \n " , str_hl [ t ] , srec - > tuid ) ;
if ( copy_msg ( cv ) )
return 1 ;
return ;
} else {
if ( tmsg - > srec ) {
debug ( " -> not %sing - still too big \n " , str_hl [ t ] ) ;
@ -1125,8 +1169,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
}
}
svars - > state [ t ] | = ST_SENT_NEW ;
if ( msgs_copied ( svars , t ) )
return 1 ;
msgs_copied ( svars , t ) ;
}
debug ( " synchronizing old entries \n " ) ;
@ -1164,8 +1207,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
fv = nfmalloc ( sizeof ( * fv ) ) ;
fv - > aux = AUX ;
fv - > srec = srec ;
if ( svars - > drv [ t ] - > set_flags ( svars - > ctx [ t ] , srec - > msg [ t ] , srec - > uid [ t ] , F_DELETED , 0 , flags_set_del , fv ) )
return 1 ;
DRIVER_CALL ( set_flags ( svars - > ctx [ t ] , srec - > msg [ t ] , srec - > uid [ t ] , F_DELETED , 0 , flags_set_del , fv ) ) ;
} else
debug ( " not %sing delete \n " , str_hl [ t ] ) ;
} else if ( ! srec - > msg [ 1 - t ] )
@ -1275,8 +1317,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
fv - > srec = srec ;
fv - > aflags = aflags ;
fv - > dflags = dflags ;
if ( svars - > drv [ t ] - > set_flags ( svars - > ctx [ t ] , srec - > msg [ t ] , srec - > uid [ t ] , aflags , dflags , flags_set_sync , fv ) )
return 1 ;
DRIVER_CALL ( set_flags ( svars - > ctx [ t ] , srec - > msg [ t ] , srec - > uid [ t ] , aflags , dflags , flags_set_sync , fv ) ) ;
} else
flags_set_sync_p2 ( svars , srec , t ) ;
}
@ -1285,12 +1326,11 @@ msgs_found_sel( sync_vars_t *svars, int t )
svars - > drv [ t ] - > commit ( svars - > ctx [ t ] ) ;
svars - > state [ t ] | = ST_SENT_FLAGS ;
if ( msgs_flags_set ( svars , t ) )
return 1 ;
return ;
}
return 0 ;
}
static int
static void
msg_copied ( int sts , int uid , copy_vars_t * vars )
{
SVARS_CHECK_CANCEL_RET ;
@ -1306,12 +1346,12 @@ msg_copied( int sts, int uid, copy_vars_t *vars )
default :
cancel_sync ( svars ) ;
free ( vars ) ;
return 1 ;
return ;
}
free ( vars ) ;
svars - > new_done [ t ] + + ;
stats ( svars ) ;
return msgs_copied ( svars , t ) ;
msgs_copied ( svars , t ) ;
}
static void
@ -1332,17 +1372,17 @@ msg_copied_p2( sync_vars_t *svars, sync_rec_t *srec, int t, message_t *tmsg, int
}
}
static int msg_found_new ( int sts , int uid , void * aux ) ;
static int sync_close ( sync_vars_t * svars , int t ) ;
static void msg_found_new ( int sts , int uid , void * aux ) ;
static void sync_close ( sync_vars_t * svars , int t ) ;
static int
static void
msgs_copied ( sync_vars_t * svars , int t )
{
sync_rec_t * srec ;
find_vars_t * fv ;
if ( ! ( svars - > state [ t ] & ST_SENT_NEW ) | | svars - > new_done [ t ] < svars - > new_total [ t ] )
return 0 ;
return ;
debug ( " finding just copied messages on %s \n " , str_ms [ t ] ) ;
for ( srec = svars - > srecs ; srec ; srec = srec - > next ) {
@ -1355,15 +1395,14 @@ msgs_copied( sync_vars_t *svars, int t )
fv = nfmalloc ( sizeof ( * fv ) ) ;
fv - > aux = AUX ;
fv - > srec = srec ;
if ( svars - > drv [ t ] - > find_msg ( svars - > ctx [ t ] , srec - > tuid , msg_found_new , fv ) )
return 1 ;
DRIVER_CALL ( find_msg ( svars - > ctx [ t ] , srec - > tuid , msg_found_new , fv ) ) ;
}
}
svars - > state [ t ] | = ST_SENT_FIND_NEW ;
return sync_close ( svars , t ) ;
sync_close ( svars , t ) ;
}
static int
static void
msg_found_new ( int sts , int uid , void * aux )
{
SVARS_CHECK_RET_VARS ( find_vars_t ) ;
@ -1382,10 +1421,10 @@ msg_found_new( int sts, int uid, void *aux )
free ( vars ) ;
svars - > find_new_done [ t ] + + ;
stats ( svars ) ;
return sync_close ( svars , t ) ;
sync_close ( svars , t ) ;
}
static int
static void
flags_set_del ( int sts , void * aux )
{
SVARS_CHECK_RET_VARS ( flag_vars_t ) ;
@ -1399,10 +1438,10 @@ flags_set_del( int sts, void *aux )
free ( vars ) ;
svars - > flags_done [ t ] + + ;
stats ( svars ) ;
return msgs_flags_set ( svars , t ) ;
msgs_flags_set ( svars , t ) ;
}
static int
static void
flags_set_sync ( int sts , void * aux )
{
SVARS_CHECK_RET_VARS ( flag_vars_t ) ;
@ -1418,7 +1457,7 @@ flags_set_sync( int sts, void *aux )
free ( vars ) ;
svars - > flags_done [ t ] + + ;
stats ( svars ) ;
return msgs_flags_set ( svars , t ) ;
msgs_flags_set ( svars , t ) ;
}
static void
@ -1448,8 +1487,8 @@ flags_set_sync_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
}
}
static int msg_trashed ( int sts , void * aux ) ;
static int msg_rtrashed ( int sts , int uid , copy_vars_t * vars ) ;
static void msg_trashed ( int sts , void * aux ) ;
static void msg_rtrashed ( int sts , int uid , copy_vars_t * vars ) ;
static int
msgs_flags_set ( sync_vars_t * svars , int t )
@ -1470,8 +1509,10 @@ msgs_flags_set( sync_vars_t *svars, int t )
debug ( " %s: trashing message %d \n " , str_ms [ t ] , tmsg - > uid ) ;
svars - > trash_total [ t ] + + ;
stats ( svars ) ;
if ( svars - > drv [ t ] - > trash_msg ( svars - > ctx [ t ] , tmsg , msg_trashed , AUX ) )
return 1 ;
sync_ref ( svars ) ;
svars - > drv [ t ] - > trash_msg ( svars - > ctx [ t ] , tmsg , msg_trashed , AUX ) ;
if ( deref_check_cancel ( svars ) )
return - 1 ;
} else
debug ( " %s: not trashing message %d - not new \n " , str_ms [ t ] , tmsg - > uid ) ;
} else {
@ -1486,7 +1527,7 @@ msgs_flags_set( sync_vars_t *svars, int t )
cv - > srec = 0 ;
cv - > msg = tmsg ;
if ( copy_msg ( cv ) )
return 1 ;
return - 1 ;
} else
debug ( " %s: not remote trashing message %d - too big \n " , str_ms [ t ] , tmsg - > uid ) ;
} else
@ -1495,10 +1536,11 @@ msgs_flags_set( sync_vars_t *svars, int t )
}
}
svars - > state [ t ] | = ST_SENT_TRASH ;
return sync_close ( svars , t ) ;
sync_close ( svars , t ) ;
return 0 ;
}
static int
static void
msg_trashed ( int sts , void * aux )
{
DECL_SVARS ;
@ -1506,14 +1548,14 @@ msg_trashed( int sts, void *aux )
if ( sts = = DRV_MSG_BAD )
sts = DRV_BOX_BAD ;
if ( check_ret ( sts , aux ) )
return 1 ;
return ;
INIT_SVARS ( aux ) ;
svars - > trash_done [ t ] + + ;
stats ( svars ) ;
return sync_close ( svars , t ) ;
sync_close ( svars , t ) ;
}
static int
static void
msg_rtrashed ( int sts , int uid , copy_vars_t * vars )
{
SVARS_CHECK_CANCEL_RET ;
@ -1525,40 +1567,39 @@ msg_rtrashed( int sts, int uid, copy_vars_t *vars )
default :
cancel_sync ( svars ) ;
free ( vars ) ;
return 1 ;
return ;
}
free ( vars ) ;
svars - > trash_done [ t ] + + ;
stats ( svars ) ;
return sync_close ( svars , t ) ;
sync_close ( svars , t ) ;
}
static int box_closed ( int sts , void * aux ) ;
static void box_closed ( int sts , void * aux ) ;
static void box_closed_p2 ( sync_vars_t * svars , int t ) ;
static int
static void
sync_close ( sync_vars_t * svars , int t )
{
if ( ( ~ svars - > state [ t ] & ( ST_SENT_FIND_NEW | ST_SENT_TRASH ) ) | |
svars - > find_new_done [ t ] < svars - > find_new_total [ t ] | |
svars - > trash_done [ t ] < svars - > trash_total [ t ] )
return 0 ;
return ;
if ( ( svars - > chan - > ops [ t ] & OP_EXPUNGE ) /*&& !(svars->state[t] & ST_TRASH_BAD)*/ ) {
debug ( " expunging %s \n " , str_ms [ t ] ) ;
return svars - > drv [ t ] - > close ( svars - > ctx [ t ] , box_closed , AUX ) ;
svars - > drv [ t ] - > close ( svars - > ctx [ t ] , box_closed , AUX ) ;
} else {
box_closed_p2 ( svars , t ) ;
}
box_closed_p2 ( svars , t ) ;
return 0 ;
}
static int
static void
box_closed ( int sts , void * aux )
{
SVARS_CHECK_RET ;
svars - > state [ t ] | = ST_DID_EXPUNGE ;
box_closed_p2 ( svars , t ) ;
return 0 ;
}
static void
@ -1655,16 +1696,23 @@ sync_bail1( sync_vars_t *svars )
static void
sync_bail2 ( sync_vars_t * svars )
{
void ( * cb ) ( int sts , void * aux ) = svars - > cb ;
void * aux = svars - > aux ;
int ret = svars - > ret ;
free ( svars - > lname ) ;
free ( svars - > nname ) ;
free ( svars - > jname ) ;
free ( svars - > dname ) ;
free ( svars ) ;
error ( " " ) ;
cb ( ret , aux ) ;
sync_deref ( svars ) ;
}
static int sync_deref ( sync_vars_t * svars )
{
if ( ! - - svars - > ref_count ) {
void ( * cb ) ( int sts , void * aux ) = svars - > cb ;
void * aux = svars - > aux ;
int ret = svars - > ret ;
free ( svars ) ;
cb ( ret , aux ) ;
return - 1 ;
}
return 0 ;
}