add forced async mode to proxy driver
to test async operation of the syncing core while using the synchronous maildir driver, we add a mode to the proxy driver where it queues callback invocations to the next main loop iteration.
This commit is contained in:
parent
be657530ee
commit
4423a932f3
|
@ -107,6 +107,7 @@ typedef unsigned long ulong;
|
||||||
#define VERBOSE 0x800
|
#define VERBOSE 0x800
|
||||||
#define KEEPJOURNAL 0x1000
|
#define KEEPJOURNAL 0x1000
|
||||||
#define ZERODELAY 0x2000
|
#define ZERODELAY 0x2000
|
||||||
|
#define FORCEASYNC 0x4000
|
||||||
|
|
||||||
extern int DFlags;
|
extern int DFlags;
|
||||||
extern int JLimit;
|
extern int JLimit;
|
||||||
|
|
|
@ -127,6 +127,9 @@ typedef struct {
|
||||||
#define DRV_CANCELED 4
|
#define DRV_CANCELED 4
|
||||||
|
|
||||||
/* All memory belongs to the driver's user, unless stated otherwise. */
|
/* All memory belongs to the driver's user, unless stated otherwise. */
|
||||||
|
// If the driver is NOT DRV_ASYNC, memory owned by the driver returned
|
||||||
|
// through callbacks MUST remain valid until a related subsequent command
|
||||||
|
// is invoked, as the proxy driver may deliver these pointers with delay.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This flag says that the driver CAN store messages with CRLFs,
|
This flag says that the driver CAN store messages with CRLFs,
|
||||||
|
@ -138,6 +141,10 @@ typedef struct {
|
||||||
This flag says that the driver will act upon (DFlags & VERBOSE).
|
This flag says that the driver will act upon (DFlags & VERBOSE).
|
||||||
*/
|
*/
|
||||||
#define DRV_VERBOSE 2
|
#define DRV_VERBOSE 2
|
||||||
|
/*
|
||||||
|
This flag says that the driver operates asynchronously.
|
||||||
|
*/
|
||||||
|
#define DRV_ASYNC 4
|
||||||
|
|
||||||
#define LIST_INBOX 1
|
#define LIST_INBOX 1
|
||||||
#define LIST_PATH 2
|
#define LIST_PATH 2
|
||||||
|
|
|
@ -3675,7 +3675,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
static uint
|
static uint
|
||||||
imap_get_caps( store_t *gctx ATTR_UNUSED )
|
imap_get_caps( store_t *gctx ATTR_UNUSED )
|
||||||
{
|
{
|
||||||
return DRV_CRLF | DRV_VERBOSE;
|
return DRV_CRLF | DRV_VERBOSE | DRV_ASYNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct driver imap_driver = {
|
struct driver imap_driver = {
|
||||||
|
|
147
src/drv_proxy.c
147
src/drv_proxy.c
|
@ -21,9 +21,12 @@
|
||||||
|
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct gen_cmd gen_cmd_t;
|
||||||
|
|
||||||
typedef union proxy_store {
|
typedef union proxy_store {
|
||||||
store_t gen;
|
store_t gen;
|
||||||
struct {
|
struct {
|
||||||
|
@ -32,6 +35,9 @@ typedef union proxy_store {
|
||||||
uint ref_count;
|
uint ref_count;
|
||||||
driver_t *real_driver;
|
driver_t *real_driver;
|
||||||
store_t *real_store;
|
store_t *real_store;
|
||||||
|
gen_cmd_t *done_cmds, **done_cmds_append;
|
||||||
|
gen_cmd_t *check_cmds, **check_cmds_append;
|
||||||
|
wakeup_t wakeup;
|
||||||
|
|
||||||
void (*bad_callback)( void *aux );
|
void (*bad_callback)( void *aux );
|
||||||
void *bad_callback_aux;
|
void *bad_callback_aux;
|
||||||
|
@ -78,8 +84,10 @@ proxy_make_flags( uchar flags, char *buf )
|
||||||
static void
|
static void
|
||||||
proxy_store_deref( proxy_store_t *ctx )
|
proxy_store_deref( proxy_store_t *ctx )
|
||||||
{
|
{
|
||||||
if (!--ctx->ref_count)
|
if (!--ctx->ref_count) {
|
||||||
|
assert( !pending_wakeup( &ctx->wakeup ) );
|
||||||
free( ctx );
|
free( ctx );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int curr_tag;
|
static int curr_tag;
|
||||||
|
@ -87,11 +95,24 @@ static int curr_tag;
|
||||||
#define GEN_CMD \
|
#define GEN_CMD \
|
||||||
uint ref_count; \
|
uint ref_count; \
|
||||||
int tag; \
|
int tag; \
|
||||||
proxy_store_t *ctx;
|
proxy_store_t *ctx; \
|
||||||
|
gen_cmd_t *next; \
|
||||||
|
void (*queued_cb)( gen_cmd_t *gcmd );
|
||||||
|
|
||||||
typedef struct {
|
struct gen_cmd {
|
||||||
GEN_CMD
|
GEN_CMD
|
||||||
} gen_cmd_t;
|
};
|
||||||
|
|
||||||
|
#define GEN_STS_CMD \
|
||||||
|
GEN_CMD \
|
||||||
|
int sts;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
gen_cmd_t gen;
|
||||||
|
struct {
|
||||||
|
GEN_STS_CMD
|
||||||
|
};
|
||||||
|
} gen_sts_cmd_t;
|
||||||
|
|
||||||
static gen_cmd_t *
|
static gen_cmd_t *
|
||||||
proxy_cmd_new( proxy_store_t *ctx, uint sz )
|
proxy_cmd_new( proxy_store_t *ctx, uint sz )
|
||||||
|
@ -113,6 +134,67 @@ proxy_cmd_done( gen_cmd_t *cmd )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_wakeup( void *aux )
|
||||||
|
{
|
||||||
|
proxy_store_t *ctx = (proxy_store_t *)aux;
|
||||||
|
|
||||||
|
gen_cmd_t *cmd = ctx->done_cmds;
|
||||||
|
assert( cmd );
|
||||||
|
if (!(ctx->done_cmds = cmd->next))
|
||||||
|
ctx->done_cmds_append = &ctx->done_cmds;
|
||||||
|
else
|
||||||
|
conf_wakeup( &ctx->wakeup, 0 );
|
||||||
|
cmd->queued_cb( cmd );
|
||||||
|
proxy_cmd_done( cmd );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_invoke_cb( gen_cmd_t *cmd, void (*cb)( gen_cmd_t * ), int checked, const char *name )
|
||||||
|
{
|
||||||
|
if (DFlags & FORCEASYNC) {
|
||||||
|
debug( "%s[% 2d] Callback queue %s%s\n", cmd->ctx->label, cmd->tag, name, checked ? " (checked)" : "" );
|
||||||
|
cmd->queued_cb = cb;
|
||||||
|
cmd->next = NULL;
|
||||||
|
if (checked) {
|
||||||
|
*cmd->ctx->check_cmds_append = cmd;
|
||||||
|
cmd->ctx->check_cmds_append = &cmd->next;
|
||||||
|
} else {
|
||||||
|
*cmd->ctx->done_cmds_append = cmd;
|
||||||
|
cmd->ctx->done_cmds_append = &cmd->next;
|
||||||
|
conf_wakeup( &cmd->ctx->wakeup, 0 );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cb( cmd );
|
||||||
|
proxy_cmd_done( cmd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_flush_checked_cmds( proxy_store_t *ctx )
|
||||||
|
{
|
||||||
|
if (ctx->check_cmds) {
|
||||||
|
*ctx->done_cmds_append = ctx->check_cmds;
|
||||||
|
ctx->done_cmds_append = ctx->check_cmds_append;
|
||||||
|
ctx->check_cmds_append = &ctx->check_cmds;
|
||||||
|
ctx->check_cmds = NULL;
|
||||||
|
conf_wakeup( &ctx->wakeup, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_cancel_checked_cmds( proxy_store_t *ctx )
|
||||||
|
{
|
||||||
|
gen_cmd_t *cmd;
|
||||||
|
|
||||||
|
while ((cmd = ctx->check_cmds)) {
|
||||||
|
if (!(ctx->check_cmds = cmd->next))
|
||||||
|
ctx->check_cmds_append = &ctx->check_cmds;
|
||||||
|
((gen_sts_cmd_t *)cmd)->sts = DRV_CANCELED;
|
||||||
|
cmd->queued_cb( cmd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//# TEMPLATE GETTER
|
//# TEMPLATE GETTER
|
||||||
static @type@proxy_@name@( store_t *gctx )
|
static @type@proxy_@name@( store_t *gctx )
|
||||||
|
@ -155,9 +237,10 @@ static @type@proxy_@name@( store_t *gctx@decl_args@ )
|
||||||
|
|
||||||
//# TEMPLATE CALLBACK
|
//# TEMPLATE CALLBACK
|
||||||
typedef union {
|
typedef union {
|
||||||
gen_cmd_t gen;
|
@gen_cmd_t@ gen;
|
||||||
struct {
|
struct {
|
||||||
GEN_CMD
|
@GEN_CMD@
|
||||||
|
@decl_cb_state@
|
||||||
void (*callback)( @decl_cb_args@void *aux );
|
void (*callback)( @decl_cb_args@void *aux );
|
||||||
void *callback_aux;
|
void *callback_aux;
|
||||||
@decl_state@
|
@decl_state@
|
||||||
|
@ -165,16 +248,24 @@ typedef union {
|
||||||
} @name@_cmd_t;
|
} @name@_cmd_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
proxy_@name@_cb( @decl_cb_args@void *aux )
|
proxy_do_@name@_cb( gen_cmd_t *gcmd )
|
||||||
{
|
{
|
||||||
@name@_cmd_t *cmd = (@name@_cmd_t *)aux;
|
@name@_cmd_t *cmd = (@name@_cmd_t *)gcmd;
|
||||||
|
|
||||||
@pre_print_cb_args@
|
@pre_print_cb_args@
|
||||||
debug( "%s[% 2d] Callback enter @name@@print_fmt_cb_args@\n", cmd->ctx->label, cmd->tag@print_pass_cb_args@ );
|
debug( "%s[% 2d] Callback enter @name@@print_fmt_cb_args@\n", cmd->ctx->label, cmd->tag@print_pass_cb_args@ );
|
||||||
@print_cb_args@
|
@print_cb_args@
|
||||||
cmd->callback( @pass_cb_args@cmd->callback_aux );
|
cmd->callback( @pass_cb_args@cmd->callback_aux );
|
||||||
debug( "%s[% 2d] Callback leave @name@\n", cmd->ctx->label, cmd->tag );
|
debug( "%s[% 2d] Callback leave @name@\n", cmd->ctx->label, cmd->tag );
|
||||||
proxy_cmd_done( &cmd->gen );
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_@name@_cb( @decl_cb_args@void *aux )
|
||||||
|
{
|
||||||
|
@name@_cmd_t *cmd = (@name@_cmd_t *)aux;
|
||||||
|
|
||||||
|
@save_cb_args@
|
||||||
|
proxy_invoke_cb( @gen_cmd@, proxy_do_@name@_cb, @checked@, "@name@" );
|
||||||
}
|
}
|
||||||
|
|
||||||
static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), void *aux )
|
static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), void *aux )
|
||||||
|
@ -190,15 +281,15 @@ static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@v
|
||||||
@print_args@
|
@print_args@
|
||||||
ctx->real_driver->@name@( ctx->real_store@pass_args@, proxy_@name@_cb, cmd );
|
ctx->real_driver->@name@( ctx->real_store@pass_args@, proxy_@name@_cb, cmd );
|
||||||
debug( "%s[% 2d] Leave @name@\n", ctx->label, cmd->tag );
|
debug( "%s[% 2d] Leave @name@\n", ctx->label, cmd->tag );
|
||||||
proxy_cmd_done( &cmd->gen );
|
proxy_cmd_done( @gen_cmd@ );
|
||||||
}
|
}
|
||||||
//# END
|
//# END
|
||||||
|
|
||||||
//# UNDEFINE list_store_print_fmt_cb_args
|
//# UNDEFINE list_store_print_fmt_cb_args
|
||||||
//# UNDEFINE list_store_print_pass_cb_args
|
//# UNDEFINE list_store_print_pass_cb_args
|
||||||
//# DEFINE list_store_print_cb_args
|
//# DEFINE list_store_print_cb_args
|
||||||
if (sts == DRV_OK) {
|
if (cmd->sts == DRV_OK) {
|
||||||
for (string_list_t *box = boxes; box; box = box->next)
|
for (string_list_t *box = cmd->boxes; box; box = box->next)
|
||||||
debug( " %s\n", box->string );
|
debug( " %s\n", box->string );
|
||||||
}
|
}
|
||||||
//# END
|
//# END
|
||||||
|
@ -217,21 +308,21 @@ static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@v
|
||||||
}
|
}
|
||||||
//# END
|
//# END
|
||||||
//# DEFINE load_box_print_fmt_cb_args , sts=%d, total=%d, recent=%d
|
//# DEFINE load_box_print_fmt_cb_args , sts=%d, total=%d, recent=%d
|
||||||
//# DEFINE load_box_print_pass_cb_args , sts, total_msgs, recent_msgs
|
//# DEFINE load_box_print_pass_cb_args , cmd->sts, cmd->total_msgs, cmd->recent_msgs
|
||||||
//# DEFINE load_box_print_cb_args
|
//# DEFINE load_box_print_cb_args
|
||||||
if (sts == DRV_OK) {
|
if (cmd->sts == DRV_OK) {
|
||||||
static char fbuf[as(Flags) + 1];
|
static char fbuf[as(Flags) + 1];
|
||||||
for (message_t *msg = msgs; msg; msg = msg->next)
|
for (message_t *msg = cmd->msgs; msg; msg = msg->next)
|
||||||
debug( " uid=%-5u flags=%-4s size=%-6u tuid=%." stringify(TUIDL) "s\n",
|
debug( " uid=%-5u flags=%-4s size=%-6u tuid=%." stringify(TUIDL) "s\n",
|
||||||
msg->uid, (msg->status & M_FLAGS) ? (proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? msg->tuid : "?" );
|
msg->uid, (msg->status & M_FLAGS) ? (proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? msg->tuid : "?" );
|
||||||
}
|
}
|
||||||
//# END
|
//# END
|
||||||
|
|
||||||
//# DEFINE find_new_msgs_print_fmt_cb_args , sts=%d
|
//# DEFINE find_new_msgs_print_fmt_cb_args , sts=%d
|
||||||
//# DEFINE find_new_msgs_print_pass_cb_args , sts
|
//# DEFINE find_new_msgs_print_pass_cb_args , cmd->sts
|
||||||
//# DEFINE find_new_msgs_print_cb_args
|
//# DEFINE find_new_msgs_print_cb_args
|
||||||
if (sts == DRV_OK) {
|
if (cmd->sts == DRV_OK) {
|
||||||
for (message_t *msg = msgs; msg; msg = msg->next)
|
for (message_t *msg = cmd->msgs; msg; msg = msg->next)
|
||||||
debug( " uid=%-5u tuid=%." stringify(TUIDL) "s\n", msg->uid, msg->tuid );
|
debug( " uid=%-5u tuid=%." stringify(TUIDL) "s\n", msg->uid, msg->tuid );
|
||||||
}
|
}
|
||||||
//# END
|
//# END
|
||||||
|
@ -251,7 +342,7 @@ static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@v
|
||||||
//# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%lld, size=%u
|
//# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%lld, size=%u
|
||||||
//# DEFINE fetch_msg_print_pass_cb_args , fbuf, (long long)cmd->data->date, cmd->data->len
|
//# DEFINE fetch_msg_print_pass_cb_args , fbuf, (long long)cmd->data->date, cmd->data->len
|
||||||
//# DEFINE fetch_msg_print_cb_args
|
//# DEFINE fetch_msg_print_cb_args
|
||||||
if (sts == DRV_OK && (DFlags & DEBUG_DRV_ALL)) {
|
if (cmd->sts == DRV_OK && (DFlags & DEBUG_DRV_ALL)) {
|
||||||
printf( "%s=========\n", cmd->ctx->label );
|
printf( "%s=========\n", cmd->ctx->label );
|
||||||
fwrite( cmd->data->data, cmd->data->len, 1, stdout );
|
fwrite( cmd->data->data, cmd->data->len, 1, stdout );
|
||||||
printf( "%s=========\n", cmd->ctx->label );
|
printf( "%s=========\n", cmd->ctx->label );
|
||||||
|
@ -281,14 +372,29 @@ static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@v
|
||||||
//# END
|
//# END
|
||||||
//# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s
|
//# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s
|
||||||
//# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2
|
//# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2
|
||||||
|
//# DEFINE set_msg_flags_checked sts == DRV_OK
|
||||||
|
|
||||||
//# DEFINE trash_msg_print_fmt_args , uid=%u
|
//# DEFINE trash_msg_print_fmt_args , uid=%u
|
||||||
//# DEFINE trash_msg_print_pass_args , msg->uid
|
//# DEFINE trash_msg_print_pass_args , msg->uid
|
||||||
|
|
||||||
|
//# DEFINE commit_cmds_print_args
|
||||||
|
proxy_flush_checked_cmds( ctx );
|
||||||
|
//# END
|
||||||
|
|
||||||
|
//# DEFINE cancel_cmds_print_cb_args
|
||||||
|
proxy_cancel_checked_cmds( cmd->ctx );
|
||||||
|
//# END
|
||||||
|
|
||||||
|
//# DEFINE free_store_print_args
|
||||||
|
proxy_cancel_checked_cmds( ctx );
|
||||||
|
//# END
|
||||||
//# DEFINE free_store_action
|
//# DEFINE free_store_action
|
||||||
proxy_store_deref( ctx );
|
proxy_store_deref( ctx );
|
||||||
//# END
|
//# END
|
||||||
|
|
||||||
|
//# DEFINE cancel_store_print_args
|
||||||
|
proxy_cancel_checked_cmds( ctx );
|
||||||
|
//# END
|
||||||
//# DEFINE cancel_store_action
|
//# DEFINE cancel_store_action
|
||||||
proxy_store_deref( ctx );
|
proxy_store_deref( ctx );
|
||||||
//# END
|
//# END
|
||||||
|
@ -325,9 +431,12 @@ proxy_alloc_store( store_t *real_ctx, const char *label )
|
||||||
ctx->gen.conf = real_ctx->conf;
|
ctx->gen.conf = real_ctx->conf;
|
||||||
ctx->ref_count = 1;
|
ctx->ref_count = 1;
|
||||||
ctx->label = label;
|
ctx->label = label;
|
||||||
|
ctx->done_cmds_append = &ctx->done_cmds;
|
||||||
|
ctx->check_cmds_append = &ctx->check_cmds;
|
||||||
ctx->real_driver = real_ctx->driver;
|
ctx->real_driver = real_ctx->driver;
|
||||||
ctx->real_store = real_ctx;
|
ctx->real_store = real_ctx;
|
||||||
ctx->real_driver->set_bad_callback( ctx->real_store, (void (*)(void *))proxy_invoke_bad_callback, ctx );
|
ctx->real_driver->set_bad_callback( ctx->real_store, (void (*)(void *))proxy_invoke_bad_callback, ctx );
|
||||||
|
init_wakeup( &ctx->wakeup, proxy_wakeup, ctx );
|
||||||
return &ctx->gen;
|
return &ctx->gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,11 +150,26 @@ for (@ptypes) {
|
||||||
} else {
|
} else {
|
||||||
if ($cmd_type eq "void " && $cmd_args =~ s/, void \(\*cb\)\( (.*)void \*aux \), void \*aux$//) {
|
if ($cmd_type eq "void " && $cmd_args =~ s/, void \(\*cb\)\( (.*)void \*aux \), void \*aux$//) {
|
||||||
my $cmd_cb_args = $1;
|
my $cmd_cb_args = $1;
|
||||||
$replace{'decl_cb_args'} = $cmd_cb_args;
|
if (length($cmd_cb_args)) {
|
||||||
$replace{'pass_cb_args'} = make_args($cmd_cb_args);
|
$replace{'decl_cb_args'} = $cmd_cb_args;
|
||||||
my $cmd_print_cb_args = $cmd_cb_args =~ s/(.*), $/, $1/r;
|
my $r_cmd_cb_args = $cmd_cb_args;
|
||||||
$replace{'print_pass_cb_args'} = make_args($cmd_print_cb_args);
|
$r_cmd_cb_args =~ s/^int sts, // or die("Callback arguments of $cmd_name don't start with sts.\n");
|
||||||
$replace{'print_fmt_cb_args'} = make_format($cmd_print_cb_args);
|
$replace{'decl_cb_state'} = $r_cmd_cb_args =~ s/, /\;\n/gr;
|
||||||
|
my $pass_cb_args = make_args($cmd_cb_args);
|
||||||
|
$replace{'save_cb_args'} = $pass_cb_args =~ s/([^,]+), /cmd->$1 = $1\;\n/gr;
|
||||||
|
$pass_cb_args =~ s/([^, ]+)/cmd->$1/g;
|
||||||
|
$replace{'pass_cb_args'} = $pass_cb_args;
|
||||||
|
$replace{'print_pass_cb_args'} = $pass_cb_args =~ s/(.*), $/, $1/r;
|
||||||
|
$replace{'print_fmt_cb_args'} = make_format($cmd_cb_args =~ s/(.*), $/, $1/r);
|
||||||
|
$replace{'gen_cmd_t'} = "gen_sts_cmd_t";
|
||||||
|
$replace{'GEN_CMD'} = "GEN_STS_CMD\n";
|
||||||
|
$replace{'gen_cmd'} = "&cmd->gen.gen";
|
||||||
|
} else {
|
||||||
|
$replace{'gen_cmd_t'} = "gen_cmd_t";
|
||||||
|
$replace{'GEN_CMD'} = "GEN_CMD\n";
|
||||||
|
$replace{'gen_cmd'} = "&cmd->gen";
|
||||||
|
}
|
||||||
|
$replace{'checked'} //= '0';
|
||||||
$template = "CALLBACK";
|
$template = "CALLBACK";
|
||||||
} elsif ($cmd_type eq "void ") {
|
} elsif ($cmd_type eq "void ") {
|
||||||
$template = "REGULAR_VOID";
|
$template = "REGULAR_VOID";
|
||||||
|
|
20
src/main.c
20
src/main.c
|
@ -713,6 +713,9 @@ main( int argc, char **argv )
|
||||||
case 'T':
|
case 'T':
|
||||||
for (; *ochar; ) {
|
for (; *ochar; ) {
|
||||||
switch (*ochar++) {
|
switch (*ochar++) {
|
||||||
|
case 'a':
|
||||||
|
DFlags |= FORCEASYNC;
|
||||||
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
DFlags |= KEEPJOURNAL;
|
DFlags |= KEEPJOURNAL;
|
||||||
JLimit = strtol( ochar, &ochar, 10 );
|
JLimit = strtol( ochar, &ochar, 10 );
|
||||||
|
@ -861,20 +864,23 @@ sync_chans( main_vars_t *mvars, int ent )
|
||||||
if (mvars->skip)
|
if (mvars->skip)
|
||||||
goto next2;
|
goto next2;
|
||||||
mvars->state[F] = mvars->state[N] = ST_FRESH;
|
mvars->state[F] = mvars->state[N] = ST_FRESH;
|
||||||
if ((DFlags & DEBUG_DRV) || (mvars->chan->stores[F]->driver->get_caps( NULL ) & mvars->chan->stores[N]->driver->get_caps( NULL ) & DRV_VERBOSE))
|
uint dcaps[2];
|
||||||
|
for (t = 0; t < 2; t++) {
|
||||||
|
mvars->drv[t] = mvars->chan->stores[t]->driver;
|
||||||
|
dcaps[t] = mvars->drv[t]->get_caps( NULL );
|
||||||
|
}
|
||||||
|
if ((DFlags & DEBUG_DRV) || (dcaps[F] & dcaps[N] & DRV_VERBOSE))
|
||||||
labels[F] = "F: ", labels[N] = "N: ";
|
labels[F] = "F: ", labels[N] = "N: ";
|
||||||
else
|
else
|
||||||
labels[F] = labels[N] = "";
|
labels[F] = labels[N] = "";
|
||||||
for (t = 0; t < 2; t++) {
|
for (t = 0; t < 2; t++) {
|
||||||
driver_t *drv = mvars->chan->stores[t]->driver;
|
store_t *ctx = mvars->drv[t]->alloc_store( mvars->chan->stores[t], labels[t] );
|
||||||
store_t *ctx = drv->alloc_store( mvars->chan->stores[t], labels[t] );
|
if ((DFlags & DEBUG_DRV) || ((DFlags & FORCEASYNC) && !(dcaps[t] & DRV_ASYNC))) {
|
||||||
if (DFlags & DEBUG_DRV) {
|
mvars->drv[t] = &proxy_driver;
|
||||||
drv = &proxy_driver;
|
|
||||||
ctx = proxy_alloc_store( ctx, labels[t] );
|
ctx = proxy_alloc_store( ctx, labels[t] );
|
||||||
}
|
}
|
||||||
mvars->drv[t] = drv;
|
|
||||||
mvars->ctx[t] = ctx;
|
mvars->ctx[t] = ctx;
|
||||||
drv->set_bad_callback( ctx, store_bad, AUX );
|
mvars->drv[t]->set_bad_callback( ctx, store_bad, AUX );
|
||||||
}
|
}
|
||||||
for (t = 0; ; t++) {
|
for (t = 0; ; t++) {
|
||||||
info( "Opening %s store %s...\n", str_fn[t], mvars->chan->stores[t]->name );
|
info( "Opening %s store %s...\n", str_fn[t], mvars->chan->stores[t]->name );
|
||||||
|
|
|
@ -334,10 +334,10 @@ sub killcfg()
|
||||||
unlink ".mbsyncrc";
|
unlink ".mbsyncrc";
|
||||||
}
|
}
|
||||||
|
|
||||||
# $options
|
# $run_async, $mbsync_options, $log_file
|
||||||
sub runsync($$)
|
sub runsync($$$)
|
||||||
{
|
{
|
||||||
my ($flags, $file) = @_;
|
my ($async, $flags, $file) = @_;
|
||||||
|
|
||||||
my $cmd;
|
my $cmd;
|
||||||
if ($use_vg) {
|
if ($use_vg) {
|
||||||
|
@ -345,6 +345,7 @@ sub runsync($$)
|
||||||
} else {
|
} else {
|
||||||
$flags .= " -D";
|
$flags .= " -D";
|
||||||
}
|
}
|
||||||
|
$flags .= " -Ta" if ($async);
|
||||||
$cmd .= "$mbsync -Tz $flags -c .mbsyncrc test";
|
$cmd .= "$mbsync -Tz $flags -c .mbsyncrc test";
|
||||||
open FILE, "$cmd 2>&1 |";
|
open FILE, "$cmd 2>&1 |";
|
||||||
my @out = <FILE>;
|
my @out = <FILE>;
|
||||||
|
@ -477,7 +478,7 @@ sub show($$$)
|
||||||
showchan("near/.mbsyncstate");
|
showchan("near/.mbsyncstate");
|
||||||
print ");\n";
|
print ");\n";
|
||||||
&writecfg(@sfx);
|
&writecfg(@sfx);
|
||||||
runsync("", "");
|
runsync(0, "", "");
|
||||||
killcfg();
|
killcfg();
|
||||||
print "my \@X$tx = (\n";
|
print "my \@X$tx = (\n";
|
||||||
showchan("near/.mbsyncstate");
|
showchan("near/.mbsyncstate");
|
||||||
|
@ -681,18 +682,14 @@ sub readfile($)
|
||||||
return @nj;
|
return @nj;
|
||||||
}
|
}
|
||||||
|
|
||||||
# $title, \@source_state, \@target_state, @channel_configs
|
# $run_async, \@source_state, \@target_state, @channel_configs
|
||||||
sub test($$$@)
|
sub test_impl($$$@)
|
||||||
{
|
{
|
||||||
my ($ttl, $sx, $tx, @sfx) = @_;
|
my ($async, $sx, $tx, @sfx) = @_;
|
||||||
|
|
||||||
return 0 if (scalar(@ARGV) && !grep { $_ eq $ttl } @ARGV);
|
|
||||||
print "Testing: ".$ttl." ...\n";
|
|
||||||
&writecfg(@sfx);
|
|
||||||
|
|
||||||
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
|
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
|
||||||
|
|
||||||
my ($xc, @ret) = runsync("-Tj", "1-initial.log");
|
my ($xc, @ret) = runsync($async, "-Tj", "1-initial.log");
|
||||||
if ($xc || ckchan("near/.mbsyncstate.new", $tx)) {
|
if ($xc || ckchan("near/.mbsyncstate.new", $tx)) {
|
||||||
print "Input:\n";
|
print "Input:\n";
|
||||||
printchan($sx);
|
printchan($sx);
|
||||||
|
@ -710,7 +707,7 @@ sub test($$$@)
|
||||||
}
|
}
|
||||||
|
|
||||||
my @nj = readfile("near/.mbsyncstate.journal");
|
my @nj = readfile("near/.mbsyncstate.journal");
|
||||||
my ($jxc, @jret) = runsync("-0 --no-expunge", "2-replay.log");
|
my ($jxc, @jret) = runsync($async, "-0 --no-expunge", "2-replay.log");
|
||||||
if ($jxc || ckstate("near/.mbsyncstate", @{ $$tx[2] })) {
|
if ($jxc || ckstate("near/.mbsyncstate", @{ $$tx[2] })) {
|
||||||
print "Journal replay failed.\n";
|
print "Journal replay failed.\n";
|
||||||
print "Options:\n";
|
print "Options:\n";
|
||||||
|
@ -729,7 +726,7 @@ sub test($$$@)
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($ixc, @iret) = runsync("", "3-verify.log");
|
my ($ixc, @iret) = runsync($async, "", "3-verify.log");
|
||||||
if ($ixc || ckchan("near/.mbsyncstate", $tx)) {
|
if ($ixc || ckchan("near/.mbsyncstate", $tx)) {
|
||||||
print "Idempotence verification run failed.\n";
|
print "Idempotence verification run failed.\n";
|
||||||
print "Input == Expected result:\n";
|
print "Input == Expected result:\n";
|
||||||
|
@ -752,7 +749,7 @@ sub test($$$@)
|
||||||
for (my $l = 1; $l <= $njl; $l++) {
|
for (my $l = 1; $l <= $njl; $l++) {
|
||||||
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
|
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
|
||||||
|
|
||||||
my ($nxc, @nret) = runsync("-Tj$l", "4-interrupt.log");
|
my ($nxc, @nret) = runsync($async, "-Tj$l", "4-interrupt.log");
|
||||||
if ($nxc != (100 + ($l & 1)) << 8) {
|
if ($nxc != (100 + ($l & 1)) << 8) {
|
||||||
print "Interrupting at step $l/$njl failed.\n";
|
print "Interrupting at step $l/$njl failed.\n";
|
||||||
print "Debug output:\n";
|
print "Debug output:\n";
|
||||||
|
@ -760,7 +757,7 @@ sub test($$$@)
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
($nxc, @nret) = runsync("-Tj", "5-resume.log");
|
($nxc, @nret) = runsync($async, "-Tj", "5-resume.log");
|
||||||
if ($nxc || ckchan("near/.mbsyncstate.new", $tx)) {
|
if ($nxc || ckchan("near/.mbsyncstate.new", $tx)) {
|
||||||
print "Resuming from step $l/$njl failed.\n";
|
print "Resuming from step $l/$njl failed.\n";
|
||||||
print "Input:\n";
|
print "Input:\n";
|
||||||
|
@ -785,6 +782,19 @@ sub test($$$@)
|
||||||
rmtree "near";
|
rmtree "near";
|
||||||
rmtree "far";
|
rmtree "far";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# $title, \@source_state, \@target_state, @channel_configs
|
||||||
|
sub test($$$@)
|
||||||
|
{
|
||||||
|
my ($ttl, $sx, $tx, @sfx) = @_;
|
||||||
|
|
||||||
|
return 0 if (scalar(@ARGV) && !grep { $_ eq $ttl } @ARGV);
|
||||||
|
print "Testing: ".$ttl." ...\n";
|
||||||
|
&writecfg(@sfx);
|
||||||
|
|
||||||
|
test_impl(0, $sx, $tx, @sfx);
|
||||||
|
test_impl(1, $sx, $tx, @sfx);
|
||||||
|
|
||||||
killcfg();
|
killcfg();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user