move whole responsibility for recycling open stores/server connections

to the drivers.
This commit is contained in:
Oswald Buddenhagen 2006-03-20 19:38:20 +00:00
parent 47e592b603
commit 7f9ece8e7e
4 changed files with 87 additions and 43 deletions

View File

@ -1036,16 +1036,14 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
} }
static void static void
imap_close_store( store_t *gctx ) imap_cancel_store( store_t *gctx )
{ {
imap_store_t *ctx = (imap_store_t *)gctx; imap_store_t *ctx = (imap_store_t *)gctx;
free_generic_messages( gctx->msgs ); free_generic_messages( gctx->msgs );
free_string_list( ctx->gen.boxes ); free_string_list( ctx->gen.boxes );
if (ctx->buf.sock.fd != -1) { if (ctx->buf.sock.fd >= 0)
imap_exec( ctx, 0, "LOGOUT" );
close( ctx->buf.sock.fd ); close( ctx->buf.sock.fd );
}
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
if (ctx->SSLContext) if (ctx->SSLContext)
SSL_CTX_free( ctx->SSLContext ); SSL_CTX_free( ctx->SSLContext );
@ -1056,6 +1054,42 @@ imap_close_store( store_t *gctx )
free( ctx ); free( ctx );
} }
static store_t *unowned;
static void
imap_disown_store( store_t *gctx )
{
free_generic_messages( gctx->msgs );
gctx->msgs = 0;
gctx->next = unowned;
unowned = gctx;
}
static store_t *
imap_own_store( store_conf_t *conf )
{
store_t *store, **storep;
for (storep = &unowned; (store = *storep); storep = &store->next)
if (store->conf == conf) {
*storep = store->next;
return store;
}
return 0;
}
static void
imap_cleanup( void )
{
store_t *ctx, *nctx;
for (ctx = unowned; ctx; ctx = nctx) {
nctx = ctx->next;
imap_exec( (imap_store_t *)ctx, 0, "LOGOUT" );
imap_cancel_store( ctx );
}
}
#ifdef HAVE_LIBSSL #ifdef HAVE_LIBSSL
static int static int
start_tls( imap_store_t *ctx ) start_tls( imap_store_t *ctx )
@ -1165,11 +1199,12 @@ do_cram_auth( imap_store_t *ctx, struct imap_cmd *cmdp, const char *prompt )
#endif #endif
static store_t * static store_t *
imap_open_store( store_conf_t *conf, store_t *oldctx ) imap_open_store( store_conf_t *conf )
{ {
imap_store_conf_t *cfg = (imap_store_conf_t *)conf; imap_store_conf_t *cfg = (imap_store_conf_t *)conf;
imap_server_conf_t *srvc = cfg->server; imap_server_conf_t *srvc = cfg->server;
imap_store_t *ctx = (imap_store_t *)oldctx; imap_store_t *ctx;
store_t **ctxp;
char *arg, *rsp; char *arg, *rsp;
struct hostent *he; struct hostent *he;
struct sockaddr_in addr; struct sockaddr_in addr;
@ -1178,16 +1213,17 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
int use_ssl; int use_ssl;
#endif #endif
if (ctx) { for (ctxp = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next)
if (((imap_store_conf_t *)(ctx->gen.conf))->server == cfg->server) { if (((imap_store_conf_t *)ctx->gen.conf)->server == srvc) {
*ctxp = ctx->gen.next;
/* One could ping the server here, but given that the idle timeout
* is at least 30 minutes, this sounds pretty pointless. */
free_string_list( ctx->gen.boxes ); free_string_list( ctx->gen.boxes );
ctx->gen.boxes = 0; ctx->gen.boxes = 0;
ctx->gen.listed = 0; ctx->gen.listed = 0;
ctx->gen.conf = conf; ctx->gen.conf = conf;
goto final; goto final;
} }
imap_close_store( &ctx->gen );
}
ctx = nfcalloc( sizeof(*ctx) ); ctx = nfcalloc( sizeof(*ctx) );
ctx->gen.conf = conf; ctx->gen.conf = conf;
@ -1372,7 +1408,7 @@ imap_open_store( store_conf_t *conf, store_t *oldctx )
return &ctx->gen; return &ctx->gen;
bail: bail:
imap_close_store( &ctx->gen ); imap_cancel_store( &ctx->gen );
return 0; return 0;
} }
@ -1739,8 +1775,11 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
struct driver imap_driver = { struct driver imap_driver = {
DRV_CRLF, DRV_CRLF,
imap_parse_store, imap_parse_store,
imap_cleanup,
imap_open_store, imap_open_store,
imap_close_store, imap_disown_store,
imap_own_store,
imap_cancel_store,
imap_list, imap_list,
imap_prepare_paths, imap_prepare_paths,
imap_prepare_opts, imap_prepare_opts,

View File

@ -93,16 +93,12 @@ maildir_parse_flags( const char *base )
return flags; return flags;
} }
static void maildir_close_store( store_t *gctx );
static store_t * static store_t *
maildir_open_store( store_conf_t *conf, store_t *oldctx ) maildir_open_store( store_conf_t *conf )
{ {
maildir_store_t *ctx; maildir_store_t *ctx;
struct stat st; struct stat st;
if (oldctx)
maildir_close_store( oldctx );
if (stat( conf->path, &st ) || !S_ISDIR(st.st_mode)) { if (stat( conf->path, &st ) || !S_ISDIR(st.st_mode)) {
error( "Maildir error: cannot open store %s\n", conf->path ); error( "Maildir error: cannot open store %s\n", conf->path );
return 0; return 0;
@ -144,13 +140,25 @@ maildir_cleanup( store_t *gctx )
} }
static void static void
maildir_close_store( store_t *gctx ) maildir_disown_store( store_t *gctx )
{ {
maildir_cleanup( gctx ); maildir_cleanup( gctx );
free_string_list( gctx->boxes ); free_string_list( gctx->boxes );
free( gctx ); free( gctx );
} }
static store_t *
maildir_own_store( store_conf_t *conf )
{
(void)conf;
return 0;
}
static void
maildir_cleanup_drv( void )
{
}
static int static int
maildir_list( store_t *gctx ) maildir_list( store_t *gctx )
{ {
@ -1226,8 +1234,11 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
struct driver maildir_driver = { struct driver maildir_driver = {
0, 0,
maildir_parse_store, maildir_parse_store,
maildir_cleanup_drv,
maildir_open_store, maildir_open_store,
maildir_close_store, maildir_disown_store,
maildir_own_store,
maildir_disown_store, /* _cancel_, but it's the same */
maildir_list, maildir_list,
maildir_prepare_paths, maildir_prepare_paths,
maildir_prepare_opts, maildir_prepare_opts,

View File

@ -143,6 +143,7 @@ typedef struct message {
#define OPEN_FIND (1<<8) #define OPEN_FIND (1<<8)
typedef struct store { typedef struct store {
struct store *next;
store_conf_t *conf; /* foreign */ store_conf_t *conf; /* foreign */
string_list_t *boxes; /* _list results - own */ string_list_t *boxes; /* _list results - own */
unsigned listed:1; /* was _list already run? */ unsigned listed:1; /* was _list already run? */
@ -176,8 +177,11 @@ typedef struct {
struct driver { struct driver {
int flags; int flags;
int (*parse_store)( conffile_t *cfg, store_conf_t **storep, int *err ); int (*parse_store)( conffile_t *cfg, store_conf_t **storep, int *err );
store_t *(*open_store)( store_conf_t *conf, store_t *oldctx ); void (*cleanup)( void );
void (*close_store)( store_t *ctx ); store_t *(*open_store)( store_conf_t *conf );
void (*disown_store)( store_t *ctx );
store_t *(*own_store)( store_conf_t *conf );
void (*cancel_store)( store_t *ctx );
int (*list)( store_t *ctx ); int (*list)( store_t *ctx );
void (*prepare_paths)( store_t *ctx ); void (*prepare_paths)( store_t *ctx );
void (*prepare_opts)( store_t *ctx, int opts ); void (*prepare_opts)( store_t *ctx, int opts );

View File

@ -190,7 +190,6 @@ int
main( int argc, char **argv ) main( int argc, char **argv )
{ {
channel_conf_t *chan; channel_conf_t *chan;
store_conf_t *conf[2];
group_conf_t *group; group_conf_t *group;
driver_t *driver[2]; driver_t *driver[2];
store_t *ctx[2]; store_t *ctx[2];
@ -441,9 +440,6 @@ main( int argc, char **argv )
ret = 0; ret = 0;
chan = channels; chan = channels;
chanptr = 0; chanptr = 0;
ctx[M] = ctx[S] = 0;
conf[M] = conf[S] = 0; /* make-gcc-happy */
driver[M] = driver[S] = 0; /* make-gcc-happy */
if (all) if (all)
multiple = channels->next != 0; multiple = channels->next != 0;
else if (argv[oind + 1]) else if (argv[oind + 1])
@ -486,23 +482,15 @@ main( int argc, char **argv )
merge_actions( chan, ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 ); merge_actions( chan, ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 );
boxes[M] = boxes[S] = cboxes = 0; boxes[M] = boxes[S] = cboxes = 0;
/* possible todo: handle master <-> slave swaps */
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
if (ctx[t]) { driver[t] = chan->stores[t]->driver;
if (conf[t] == chan->stores[t]) ctx[t] = driver[t]->own_store( chan->stores[t] );
continue;
if (conf[t]->driver != chan->stores[t]->driver) {
driver[t]->close_store( ctx[t] );
ctx[t] = 0;
} }
} for (t = 0; t < 2; t++)
conf[t] = chan->stores[t]; if (!ctx[t] && !(ctx[t] = driver[t]->open_store( chan->stores[t] ))) {
driver[t] = conf[t]->driver;
if (!(ctx[t] = driver[t]->open_store( chan->stores[t], ctx[t] ))) {
ret = 1; ret = 1;
goto next; goto next;
} }
}
info( "Channel %s\n", chan->name ); info( "Channel %s\n", chan->name );
if (list && multiple) if (list && multiple)
printf( "%s:\n", chan->name ); printf( "%s:\n", chan->name );
@ -523,7 +511,7 @@ main( int argc, char **argv )
if (!ctx[t]->listed) { if (!ctx[t]->listed) {
if (driver[t]->list( ctx[t] ) != DRV_OK) { if (driver[t]->list( ctx[t] ) != DRV_OK) {
screwt: screwt:
driver[t]->close_store( ctx[t] ); driver[t]->cancel_store( ctx[t] );
ctx[t] = 0; ctx[t] = 0;
ret = 1; ret = 1;
goto next; goto next;
@ -584,6 +572,10 @@ main( int argc, char **argv )
free_string_list( cboxes ); free_string_list( cboxes );
free_string_list( boxes[M] ); free_string_list( boxes[M] );
free_string_list( boxes[S] ); free_string_list( boxes[S] );
if (ctx[M])
driver[M]->disown_store( ctx[M] );
if (ctx[S])
driver[S]->disown_store( ctx[S] );
if (all) { if (all) {
if (!(chan = chan->next)) if (!(chan = chan->next))
break; break;
@ -595,10 +587,8 @@ main( int argc, char **argv )
break; break;
} }
} }
if (ctx[S]) for (t = 0; t < N_DRIVERS; t++)
driver[S]->close_store( ctx[S] ); drivers[t]->cleanup();
if (ctx[M])
driver[M]->close_store( ctx[M] );
return ret; return ret;
} }