--- l2_channel.c 2001/09/27 13:56:35 1.20
+++ l2_channel.c 2001/11/03 22:51:36 1.21
@@ -51,7 +51,7 @@
* Last-modified: 2000-09-28/14:40
* Name: l2_ch_lifecycle
* Version: eo/1.0
- * H4sIAIsvszsCA62WTW/bMAyGz/WvENBzM5KyPnwusGFAdtp1l8BVWgOZUyTuhv77
+ * H4sIAGdztDsCA62WTW/bMAyGz/WvENBzM5KyPnwusGFAdtp1l8BVWgOZUyTuhv77
* kfKHnC4t5CZJ7JAO3kcUKUq5/fr9m9IrKtab9uFYb55DcR/aLhyKH6E7NHWxDh17
* ShUIsAIofjbt4y4Ud1QgASgqQGlSt3V8Fai0AoV8gTJyI76xLD6Tb35iPSpybNlS
* PsknV5po5WC0BZZRWSlL8km+tlYsa3MwJfAP6Kdokl8iltHKwjiwJ5jJL52DbIxB
@@ -84,12 +84,16 @@
/* initialize channel structure */
ch->state = L2_CHSTATE_CREATED;
- ch->downstream = NULL;
+ ch->parent = NULL;
+ ch->sibling = NULL;
+ ch->child = NULL;
memset(&ch->context, 0, sizeof(l2_context_t));
memcpy(&ch->handler, h, sizeof(l2_handler_t));
ch->rvErrorInfo = L2_OK;
ch->szErrorInfo[0] = '\0';
ch->szError[0] = '\0';
+ ch->levelmask = L2_LEVEL_ALL;
+ ch->flushmask = L2_LEVEL_NONE;
/* (optionally) perform create operation in handler */
if (ch->handler.create != NULL) {
@@ -102,6 +106,84 @@
return ch;
}
+/* stack channel on top of another channel */
+l2_result_t l2_channel_stack(l2_channel_t *ch, l2_channel_t *chP)
+{
+ l2_channel_t *chT;
+
+ /* argument sanity check */
+ if (ch == NULL || chP == NULL)
+ return L2_ERR_ARG;
+
+ /* make sure both channels are in state "created" */
+ if ( ch->state != L2_CHSTATE_CREATED
+ || chP->state != L2_CHSTATE_CREATED)
+ return L2_ERR_USE;
+
+ /* make sure parent channel is a filter channel */
+ if (chP->handler.type != L2_CHANNEL_FILTER)
+ return L2_ERR_USE;
+
+ /* make sure child still has no parent */
+ if (ch->parent != NULL)
+ return L2_ERR_USE;
+
+ /* stack the two channels */
+ ch->parent = chP;
+ if (chP->child == NULL)
+ chP->child = ch;
+ else {
+ chT = chP->child;
+ while (chT->sibling != NULL)
+ chT = chT->sibling;
+ chT->sibling = ch;
+ }
+
+ return L2_OK;
+}
+
+/* return upstream channel */
+l2_result_t l2_channel_upstream(l2_channel_t *ch, l2_channel_t **chU)
+{
+ /* argument sanity check */
+ if (ch == NULL || chU == NULL)
+ return L2_ERR_ARG;
+
+ /* determine parent/upstream channel */
+ *chU = ch->parent;
+
+ return (*chU != NULL ? L2_OK : L2_ERR_CH);
+}
+
+/* return (subsequent) downstream channel(s) */
+l2_result_t l2_channel_downstream(l2_channel_t *ch, l2_channel_t **chD)
+{
+ /* argument sanity check */
+ if (ch == NULL || chD == NULL)
+ return L2_ERR_ARG;
+
+ /* determine (next) downstream/child channel */
+ if (*chD == NULL)
+ *chD = ch->child;
+ else
+ *chD = (*chD)->sibling;
+
+ return (*chD != NULL ? L2_OK : L2_ERR_CH);
+}
+
+/* return channel type */
+l2_result_t l2_channel_type(l2_channel_t *ch, l2_chtype_t *type)
+{
+ /* argument sanity check */
+ if (ch == NULL || type == NULL)
+ return L2_ERR_ARG;
+
+ /* return type */
+ (*type) = ch->handler.type;
+
+ return L2_OK;
+}
+
/* configure channel */
l2_result_t l2_channel_configure(l2_channel_t *ch, const char *fmt, ...)
{
@@ -126,10 +208,12 @@
return rv;
}
-/* open channel (stack) */
+/* open channel */
l2_result_t l2_channel_open(l2_channel_t *ch)
{
l2_result_t rv;
+ l2_result_t rvD;
+ l2_channel_t *chD;
/* argument sanity check */
if (ch == NULL)
@@ -139,29 +223,42 @@
if (ch->state != L2_CHSTATE_CREATED)
return L2_ERR_USE;
- /* skip empty open handlers on channel stack */
- while (ch != NULL && ch->handler.open == NULL) {
- ch->state = L2_CHSTATE_OPENED;
- ch = ch->downstream;
+ /* perform operation */
+ if (ch->handler.open != NULL)
+ rv = ch->handler.open(&ch->context, ch);
+ else
+ rv = L2_OK_PASS;
+
+ /* optionally pass operation downstream */
+ if (rv == L2_OK_PASS) {
+ rv = L2_OK;
+ chD = NULL;
+ while (l2_channel_downstream(ch, &chD) == L2_OK)
+ if ((rvD = l2_channel_open(chD)) != L2_OK)
+ rv = rvD;
+ if (rv != L2_OK) {
+ chD = NULL;
+ while (l2_channel_downstream(ch, &chD) == L2_OK)
+ l2_channel_close(chD);
+ }
}
- if (ch == NULL)
- return L2_ERR_USE;
- /* pass operation to handler */
- rv = ch->handler.open(&ch->context, ch);
+ /* mark channel as opened */
if (rv == L2_OK)
ch->state = L2_CHSTATE_OPENED;
return rv;
}
-/* write to channel (stack) */
+/* write to channel */
l2_result_t l2_channel_write(l2_channel_t *ch, l2_level_t level, const char *buf, size_t bufsize)
{
l2_result_t rv;
+ l2_result_t rvD;
+ l2_channel_t *chD;
/* argument sanity check */
- if (ch == NULL || buf == NULL)
+ if (ch == NULL || level == 0 || buf == NULL)
return L2_ERR_ARG;
/* make sure channel is in state "opened" */
@@ -172,14 +269,20 @@
if (bufsize == 0)
return L2_OK;
- /* walk to next available write handler */
- while (ch != NULL && ch->handler.write == NULL)
- ch = ch->downstream;
- if (ch == NULL)
- return L2_ERR_USE;
-
- /* pass operation to handler */
- rv = ch->handler.write(&ch->context, ch, level, buf, bufsize);
+ /* perform operation */
+ if (ch->handler.write != NULL)
+ rv = ch->handler.write(&ch->context, ch, level, buf, bufsize);
+ else
+ rv = L2_OK_PASS;
+
+ /* optionally pass operation downstream */
+ if (rv == L2_OK_PASS) {
+ rv = L2_OK;
+ chD = NULL;
+ while (l2_channel_downstream(ch, &chD) == L2_OK)
+ if ((rvD = l2_channel_write(chD, level, buf, bufsize)) != L2_OK)
+ rv = rvD;
+ }
return rv;
}
@@ -188,6 +291,8 @@
l2_result_t l2_channel_flush(l2_channel_t *ch)
{
l2_result_t rv;
+ l2_result_t rvD;
+ l2_channel_t *chD;
/* argument sanity check */
if (ch == NULL)
@@ -197,14 +302,20 @@
if (ch->state != L2_CHSTATE_OPENED)
return L2_ERR_USE;
- /* walk to next available flush handler */
- while (ch != NULL && ch->handler.flush == NULL)
- ch = ch->downstream;
- if (ch == NULL)
- return L2_ERR_USE;
-
- /* pass operation to handler */
- rv = ch->handler.flush(&ch->context, ch);
+ /* perform operation */
+ if (ch->handler.flush != NULL)
+ rv = ch->handler.flush(&ch->context, ch);
+ else
+ rv = L2_OK_PASS;
+
+ /* optionally pass operation downstream */
+ if (rv == L2_OK_PASS) {
+ rv = L2_OK;
+ chD = NULL;
+ while (l2_channel_downstream(ch, &chD) == L2_OK)
+ if ((rvD = l2_channel_flush(chD)) != L2_OK)
+ rv = rvD;
+ }
return rv;
}
@@ -213,6 +324,8 @@
l2_result_t l2_channel_close(l2_channel_t *ch)
{
l2_result_t rv;
+ l2_result_t rvD;
+ l2_channel_t *chD;
/* argument sanity check */
if (ch == NULL)
@@ -222,16 +335,22 @@
if (ch->state != L2_CHSTATE_OPENED)
return L2_ERR_USE;
- /* walk to next available close handler */
- while (ch != NULL && ch->handler.close == NULL) {
- ch->state = L2_CHSTATE_CREATED;
- ch = ch->downstream;
+ /* perform operation */
+ if (ch->handler.close != NULL)
+ rv = ch->handler.close(&ch->context, ch);
+ else
+ rv = L2_OK_PASS;
+
+ /* optionally pass operation downstream */
+ if (rv == L2_OK_PASS) {
+ rv = L2_OK;
+ chD = NULL;
+ while (l2_channel_downstream(ch, &chD) == L2_OK)
+ if ((rvD = l2_channel_close(chD)) != L2_OK)
+ rv = rvD;
}
- if (ch == NULL)
- return L2_ERR_USE;
- /* pass operation to handler */
- rv = ch->handler.close(&ch->context, ch);
+ /* mark channel as closed */
if (rv == L2_OK)
ch->state = L2_CHSTATE_CREATED;
@@ -242,6 +361,8 @@
l2_result_t l2_channel_destroy(l2_channel_t *ch)
{
l2_result_t rv;
+ l2_result_t rvD;
+ l2_channel_t *chD;
/* argument sanity check */
if (ch == NULL)
@@ -252,18 +373,24 @@
if ((rv = l2_channel_close(ch)) != L2_OK)
return rv;
- /* walk to next available destroy handler */
- while (ch != NULL && ch->handler.destroy == NULL)
- ch = ch->downstream;
-
- /* pass operation to handler */
- if (ch != NULL)
+ /* perform operation */
+ if (ch->handler.destroy != NULL)
rv = ch->handler.destroy(&ch->context, ch);
else
+ rv = L2_OK_PASS;
+
+ /* optionally pass operation downstream */
+ if (rv == L2_OK_PASS) {
rv = L2_OK;
+ chD = NULL;
+ while (l2_channel_downstream(ch, &chD) == L2_OK)
+ if ((rvD = l2_channel_destroy(chD)) != L2_OK)
+ rv = rvD;
+ }
/* free channel structure */
- free(ch);
+ if (rv == L2_OK)
+ free(ch);
return rv;
}
@@ -332,45 +459,3 @@
return ch->szError;
}
-/* stack channel on top of another channel */
-l2_result_t l2_channel_stack(l2_channel_t *ch, l2_channel_t *chTop)
-{
- /* argument sanity check */
- if (ch == NULL || chTop == NULL)
- return L2_ERR_ARG;
-
- /* make sure both channels are in state "created" */
- if ( ch->state != L2_CHSTATE_CREATED
- || chTop->state != L2_CHSTATE_CREATED)
- return L2_ERR_USE;
-
- /* make sure top channel is a filter channel */
- if (chTop->handler.type != L2_CHANNEL_FILTER)
- return L2_ERR_USE;
-
- /* stack the channels */
- chTop->downstream = ch;
-
- return L2_OK;
-}
-
-/* return downstream channel */
-l2_channel_t *l2_channel_downstream(l2_channel_t *ch)
-{
- /* argument sanity check */
- if (ch == NULL)
- return NULL;
-
- return ch->downstream;
-}
-
-/* return channel type */
-l2_chtype_t l2_channel_type(l2_channel_t *ch)
-{
- /* argument sanity check */
- if (ch == NULL)
- return L2_CHANNEL_FILTER; /* FIXME */
-
- return ch->handler.type;
-}
-
|