Add CHAN_IGNORE_DUP to ignore duplicates

This commit is contained in:
Rodrigo Arias 2023-03-13 12:17:28 +01:00 committed by Rodrigo Arias Mallo
parent ab3e823134
commit e625897766
3 changed files with 69 additions and 25 deletions

View File

@ -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;

View File

@ -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,
}; };

View File

@ -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;
} }