Add CHAN_IGNORE_DUP to ignore duplicates
This commit is contained in:
parent
ab3e823134
commit
e625897766
@ -63,22 +63,6 @@ set_dirty(struct chan *chan)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
check_duplicates(struct chan *chan, struct value *v)
|
|
||||||
{
|
|
||||||
/* If duplicates are allowed just skip the check */
|
|
||||||
if (chan->prop[CHAN_ALLOW_DUP])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (value_is_equal(&chan->last_value, v)) {
|
|
||||||
err("%s: same value as last_value %s",
|
|
||||||
chan->name, value_str(chan->last_value));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
chan_set(struct chan *chan, struct value value)
|
chan_set(struct chan *chan, struct value value)
|
||||||
{
|
{
|
||||||
@ -92,10 +76,20 @@ chan_set(struct chan *chan, struct value value)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_duplicates(chan, &value) != 0) {
|
/* If duplicates are allowed just skip the check */
|
||||||
err("%s: cannot set duplicated value", chan->name);
|
if (!chan->prop[CHAN_ALLOW_DUP]) {
|
||||||
|
if (value_is_equal(&chan->last_value, &value)) {
|
||||||
|
if (chan->prop[CHAN_IGNORE_DUP]) {
|
||||||
|
dbg("%s: value already set to %s",
|
||||||
|
chan->name, value_str(value));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
err("%s: same value as last_value %s",
|
||||||
|
chan->name, value_str(chan->last_value));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dbg("%s: sets value to %s", chan->name, value_str(value));
|
dbg("%s: sets value to %s", chan->name, value_str(value));
|
||||||
chan->data.value = value;
|
chan->data.value = value;
|
||||||
@ -127,10 +121,20 @@ chan_push(struct chan *chan, struct value value)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_duplicates(chan, &value) != 0) {
|
/* If duplicates are allowed just skip the check */
|
||||||
err("%s: cannot push a duplicated value", chan->name);
|
if (!chan->prop[CHAN_ALLOW_DUP]) {
|
||||||
|
if (value_is_equal(&chan->last_value, &value)) {
|
||||||
|
if (chan->prop[CHAN_IGNORE_DUP]) {
|
||||||
|
dbg("%s: value already set to %s",
|
||||||
|
chan->name, value_str(value));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
err("%s: same value as last_value %s",
|
||||||
|
chan->name, value_str(chan->last_value));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct chan_stack *stack = &chan->data.stack;
|
struct chan_stack *stack = &chan->data.stack;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ enum chan_type {
|
|||||||
enum chan_prop {
|
enum chan_prop {
|
||||||
CHAN_DIRTY_WRITE = 0,
|
CHAN_DIRTY_WRITE = 0,
|
||||||
CHAN_ALLOW_DUP,
|
CHAN_ALLOW_DUP,
|
||||||
|
CHAN_IGNORE_DUP,
|
||||||
CHAN_MAXPROP,
|
CHAN_MAXPROP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +41,8 @@ test_dirty(void)
|
|||||||
|
|
||||||
if (chan_flush(&chan) != 0)
|
if (chan_flush(&chan) != 0)
|
||||||
die("chan_flush failed\n");
|
die("chan_flush failed\n");
|
||||||
|
|
||||||
|
err("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -72,10 +74,14 @@ test_single(void)
|
|||||||
|
|
||||||
if (!value_is_equal(&value, &one))
|
if (!value_is_equal(&value, &one))
|
||||||
die("chan_read returned unexpected value\n");
|
die("chan_read returned unexpected value\n");
|
||||||
|
|
||||||
|
err("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test that writting the same value to a channel raises an error, but not if we
|
||||||
|
* set the CHAN_ALLOW_DUP flag */
|
||||||
static void
|
static void
|
||||||
test_duplicate(void)
|
test_allow_dup(void)
|
||||||
{
|
{
|
||||||
struct chan chan;
|
struct chan chan;
|
||||||
chan_init(&chan, CHAN_SINGLE, "testchan");
|
chan_init(&chan, CHAN_SINGLE, "testchan");
|
||||||
@ -90,12 +96,44 @@ test_duplicate(void)
|
|||||||
if (chan_set(&chan, value_int64(1)) == 0)
|
if (chan_set(&chan, value_int64(1)) == 0)
|
||||||
die("chan_set didn't fail\n");
|
die("chan_set didn't fail\n");
|
||||||
|
|
||||||
/* Now enable duplicates */
|
/* Allow duplicates */
|
||||||
chan_prop_set(&chan, CHAN_ALLOW_DUP, 1);
|
chan_prop_set(&chan, CHAN_ALLOW_DUP, 1);
|
||||||
|
|
||||||
/* Then it should allow writting the same value */
|
/* Then it should allow writting the same value */
|
||||||
if (chan_set(&chan, value_int64(1)) != 0)
|
if (chan_set(&chan, value_int64(1)) != 0)
|
||||||
die("chan_set failed\n");
|
die("chan_set failed\n");
|
||||||
|
|
||||||
|
/* Also ensure the channel is dirty */
|
||||||
|
if (!chan.is_dirty)
|
||||||
|
die("chan is not dirty");
|
||||||
|
|
||||||
|
err("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test that writting the same value to a channel with the flag CHAN_IGNORE_DUP,
|
||||||
|
* causes the channel to remain clean (without the is_dirty flag set) */
|
||||||
|
static void
|
||||||
|
test_ignore_dup(void)
|
||||||
|
{
|
||||||
|
struct chan chan;
|
||||||
|
chan_init(&chan, CHAN_SINGLE, "testchan");
|
||||||
|
chan_prop_set(&chan, CHAN_IGNORE_DUP, 1);
|
||||||
|
|
||||||
|
if (chan_set(&chan, value_int64(1)) != 0)
|
||||||
|
die("chan_set failed\n");
|
||||||
|
|
||||||
|
if (chan_flush(&chan) != 0)
|
||||||
|
die("chan_flush failed\n");
|
||||||
|
|
||||||
|
/* Write the same value */
|
||||||
|
if (chan_set(&chan, value_int64(1)) != 0)
|
||||||
|
die("chan_set failed");
|
||||||
|
|
||||||
|
/* And ensure the channel is not dirty */
|
||||||
|
if (chan.is_dirty)
|
||||||
|
die("chan is dirty");
|
||||||
|
|
||||||
|
err("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
//static void
|
//static void
|
||||||
@ -159,7 +197,8 @@ int main(void)
|
|||||||
{
|
{
|
||||||
test_single();
|
test_single();
|
||||||
test_dirty();
|
test_dirty();
|
||||||
test_duplicate();
|
test_allow_dup();
|
||||||
|
test_ignore_dup();
|
||||||
//test_stack();
|
//test_stack();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user