move whole responsibility for recycling open stores/server connections
to the drivers.
This commit is contained in:
parent
47e592b603
commit
7f9ece8e7e
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
34
src/main.c
34
src/main.c
|
@ -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) {
|
for (t = 0; t < 2; t++)
|
||||||
driver[t]->close_store( ctx[t] );
|
if (!ctx[t] && !(ctx[t] = driver[t]->open_store( chan->stores[t] ))) {
|
||||||
ctx[t] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conf[t] = 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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user