Home
1 application Binary restricted distribution Non-commercial use only Can modify source Read full license | More Info
1 application Binary restricted distribution Commercial use allowed Can modify source 6 months support Read full license | More Info
5 applications Binary restricted distribution Commercial use allowed Can modify source 6 months support Read full license | More Info
5 projects Source and binary distribution Commercial use allowed Can modify source 6 months support Read full license | More Info
Starting from $ 19.99
Integration time
Saves you
U-Streams Library
The Problem
UNIX and its variants provide only stdout and stderr as standard write streams available to fprintf(). When wanting to direct messages elsewhere, it is necessary to make other arrangements for output; either via a command-line redirect, through internal management within a program itself, or some other (most-likely) non-trivial method (think pipes and sockets).
Modern systems, however, are very often required to send messages to multiple destinations, e.g., a disk-file, a database logger, alert and monitoring systems, auto-updating web-sites, UI displays, e-mail and twitter accounts, other programs, and the list goes on. When multiple destinations are necessary for the same message, this message needs to be duplicated for each destination, making coding annyoing, repetitive, and increasingly difficult to manage.
But what if there were a way to write a message just once in your program, while elsewhere it can be handled and forwarded to any number or kind of destinations without headache?
And wouldn't it be even nicer to be able to use newly named write streams that allow message type deliniation through more than just the two standard streams provided? For example, why not extend the standard stream concept to include stdInfo, stdWarn, and stdDbug?
The Solution
With this C source code library, a programmer can now:
Features:
Works especially well when forking a program. Since all file descriptors are inherited by the child, all messages written by the child will be processed by the same callback routine, guaranteeing single concurrancy of message processing, i.e., no collisions regardless the number of children demanding attention.
It Is Extensible: In general, new streams can be created to be used as a channel to transmit anything to go anywhere and/or do anything.
Creating a new stream is as simple as:
Advantages:
Deliverables:
Target Users:
Technical Requirements:
Installation:
The basic order of U-Streams functions:
A sample coded implementation is below demonstrating:
#include
#include
#include
#include
#include "ustreams.h"
/*
Copyright Notice:
Richard Ivor
2012 - All rights reserved
*/
// our program name
static gchar *procName;
static gchar *dbPrefix[USTREAMS_TTL_STREAMS] = { "LOG", "ERR", "INFO", "WARN", "DBUG"};
#define USTREAMS_INSERT_SQL "INSERT INTO `LOGS` (type, msg) VALUES ('%s', '%s')"
static void ustreamToDB(USTREAMS_STREAM stream, const char *msg)
{ // write message to DB, adding a descriptive prefix
gboolean shutDown = USTREAMS_SHUTTING_DOWN(msg);
gchar *dbMsg;
switch (shutDown)
{
case FALSE:
{
gchar *dbMsg = g_strdup_printf(USTREAMS_INSERT_SQL, dbPrefix[stream], msg);
// insert code to write the message to a Database
// ...
g_free(dbMsg);
}
break;
case TRUE:
{ // UStream is shutting down
// Execute any shutdown/clean-up operations here, e.g., a DB disconnect?
}
break;
}
return;
}
static void ustreamToDisk(USTREAMS_STREAM stream, const char *msg)
{ // write messages to individual disk file based on stream, adding a prefix timestamp
gboolean shutDown = USTREAMS_SHUTTING_DOWN(msg);
gchar *diskMsg;
switch (shutDown)
{
case FALSE:
{ // construct and output the message
diskMsg = g_strdup_printf("%s%s\n", timeStr, msg);
}
break;
case TRUE:
{ // shutting down, make msg and close our disk file pointers
// construct and output the message
diskMsg = g_strdup_printf("%s%s\n", timeStr, "Program Shutdown\n");
}
break;
}
g_free(diskMsg);
return;
}
static void ustreamToEmail(USTREAMS_STREAM stream, const char *msg)
{ // send warning and err messages to one or more email addresses
gboolean shutDown = USTREAMS_SHUTTING_DOWN(msg);
gchar *subject, *body;
switch (shutDown)
{
case FALSE: // construct subject and body of message using the msg being passed in
subject = g_strdup_printf("%s: Warning/Error", procName);
body = g_strdup_printf("%s", msg);
break;
case TRUE: // construct subject and body of message based on fact that
// the stream is shutting down, for example:
subject = g_strdup_printf("%s: Shutdown Msg", procName);
body = g_strdup_printf("Program %s has Completed and is Shutting Down.\n", procName);
break;
}
// send message to all relevant email recipients
// or perhaps to a twitter account,
// or to another program for further processing
// ...
// ...
g_free(subject);
g_free(body);
return;
}
// a fake successful connection to a database
// reverse comment these lines for example of simulated successful and failed DB connections
//#define CONNECTTODB FALSE
#define CONNECTTODB TRUE
int main(int argc, char **argv)
{
procName = g_strdup("ustreams-example");
fprintf(stdout, "Before initializing ustreams, stdout works as normal...\n");
fprintf(stdout, "But all messages issued after ustream initialisation will now be intercepted by the ustreams library.\n");
fprintf(stdout, "Check the files in the logs directory for all further messages.\n");
// initialize ustreams
// example init call to *not* re-direct stdout or stderr
// if (!ustreams_init(USTREAMS_STDNONE, TRUE, TRUE))
if (!ustreams_init(USTREAMS_STDIN | USTREAMS_STDOUT | USTREAMS_STDERR, TRUE, TRUE))
{
fprintf(stderr, "Initialisation of U-Stream Library failed, Necessarily Quitting...\n");
exit(-1);
}
fprintf(stdout, "So this message, now, will not be seen in a normal terminal output,\n"
"\tbut in our disk-file instead.\n");
fprintf(stdout, "If you desire that stdout should continue sending to the terminal,\n"
"\tyou have the option to remove it from the list of streams that the\n"
"\tustreams library will intercept.\n");
// register all streams for messages to be written to a disk-file
ustreams_register(USTREAMS_REGISTER, USTREAMS_LOG, ustreamToDisk);
ustreams_register(USTREAMS_REGISTER, USTREAMS_INFO, ustreamToDisk);
ustreams_register(USTREAMS_REGISTER, USTREAMS_WARN, ustreamToDisk);
ustreams_register(USTREAMS_REGISTER, USTREAMS_ERR, ustreamToDisk);
ustreams_register(USTREAMS_REGISTER, USTREAMS_DBUG, ustreamToDisk);
// additionally register warning and error streams to be forwarded via email to somewhere relevant
ustreams_register(USTREAMS_REGISTER, USTREAMS_WARN, ustreamToEmail);
ustreams_register(USTREAMS_REGISTER, USTREAMS_ERR, ustreamToEmail);
// All callbacks are now registered, but since we set initial msg cacheing to TRUE,
// we won't "see" any messages until we tell them to be forwarded to our callbacks.
// This is desirable since some programs may want to confirm success of some event before proceeding
// e.g., successfully connecting to a DB
fprintf(stdout, "Attempting connection to Database FOO\n");
if (CONNECTTODB == FALSE)
{
fprintf(stdout, "Connection to DB FOO Failed!\n");
fprintf(stderr, "Connection to DB FOO Failed!\n");
ustreams_cmd(USTREAMS_SHUTDOWN);
exit(-1);
}
fprintf(stdout, "Connection to DB FOO successful.\n");
// connection to DB is successful, so register all streams for our DB writer callbacks
ustreams_register(USTREAMS_REGISTER, USTREAMS_LOG, ustreamToDB);
ustreams_register(USTREAMS_REGISTER, USTREAMS_INFO, ustreamToDB);
ustreams_register(USTREAMS_REGISTER, USTREAMS_WARN, ustreamToDB);
ustreams_register(USTREAMS_REGISTER, USTREAMS_ERR, ustreamToDB);
ustreams_register(USTREAMS_REGISTER, USTREAMS_DBUG, ustreamToDB);
// convert ustream processing from internal cacheing to sending to our callbacks
// all messages cached to this point in time are also forwarded to the callbacks immediately
ustreams_cmd(USTREAMS_OUTPUT);
fprintf(stdout, "A stdout message\n");
fprintf(stderr, "A stderr message\n");
fprintf(stdinfo, "A stdinfo message\n");
fprintf(stdwarn, "A stdwarn message\n");
fprintf(stddbug, "A stddbug message\n");
// now we de-register the Write-to-Disk callback for all streams
ustreams_register(USTREAMS_DEREGISTER, USTREAMS_OUT, ustreamToDisk);
ustreams_register(USTREAMS_DEREGISTER, USTREAMS_INFO, ustreamToDisk);
ustreams_register(USTREAMS_DEREGISTER, USTREAMS_WARN, ustreamToDisk);
ustreams_register(USTREAMS_DEREGISTER, USTREAMS_ERR, ustreamToDisk);
ustreams_register(USTREAMS_DEREGISTER, USTREAMS_DBUG, ustreamToDisk);
// these messages, then, will only get delivered to the callbacks still registered
// N.B. all messages sent to a stream having no callback registration are silently droppped
fprintf(stdout, "A stdout message, no longer delivered to Disk\n");
fprintf(stderr, "A stderr message, no longer delivered to Disk\n");
fprintf(stdInfo, "A stdInfo message, no longer delivered to Disk\n");
fprintf(stdWarn, "A stdWarn message, no longer delivered to Disk\n");
fprintf(stdDbug, "A stdDbug message, no longer delivered to Disk\n");
ustreams_cmd(USTREAMS_SHUTDOWN);
exit(0);
}
The Sample Implementation provided with the delivery provides a completed implementation of the sample code above. Output to DB and e-mail is simulated by writing to a disk file.
The complete sample implementation generates the following output results:
::::::::::::::
ustreams-example.DB.dbug
::::::::::::::
INSERT INTO `LOGS` (type, msg) VALUES ('DBUG', 'A stdDbug message, first cached')
INSERT INTO `LOGS` (type, msg) VALUES ('DBUG', 'A stdDbug message, not cached')
INSERT INTO `LOGS` (type, msg) VALUES ('DBUG', 'A stdDbug message, no longer delivered to Disk File')
::::::::::::::
ustreams-example.DB.err
::::::::::::::
INSERT INTO `LOGS` (type, msg) VALUES ('ERR', 'A stderr message, first cached')
INSERT INTO `LOGS` (type, msg) VALUES ('ERR', 'A stderr message, not cached')
INSERT INTO `LOGS` (type, msg) VALUES ('ERR', 'A stderr message, no longer delivered to Disk File')
::::::::::::::
ustreams-example.DB.info
::::::::::::::
INSERT INTO `LOGS` (type, msg) VALUES ('INFO', 'A stdInfo message, first cached')
INSERT INTO `LOGS` (type, msg) VALUES ('INFO', 'A stdInfo message, not cached')
INSERT INTO `LOGS` (type, msg) VALUES ('INFO', 'A stdInfo message, no longer delivered to Disk File')
::::::::::::::
ustreams-example.DB.log
::::::::::::::
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'So this message, now, will not be seen in a normal terminal output,')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', ' but in our disk-file instead.')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'If you desire that stdout or stderr should continue sending to the terminal,')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', ' you have the option to remove one or both from the ustreams_init() command.')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', ' In this case, the U-Streams library will not intercept these streams.')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'A stdout message, first cached')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'Attempting connection to Database FOO')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'Connection to DB FOO successful.')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'A stdout message, not cached')
INSERT INTO `LOGS` (type, msg) VALUES ('LOG', 'A stdout message, no longer delivered to Disk File')
::::::::::::::
ustreams-example.DB.warn
::::::::::::::
INSERT INTO `LOGS` (type, msg) VALUES ('WARN', 'A stdWarn message, first cached')
INSERT INTO `LOGS` (type, msg) VALUES ('WARN', 'A stdWarn message, not cached')
INSERT INTO `LOGS` (type, msg) VALUES ('WARN', 'A stdWarn message, no longer delivered to Disk File')
::::::::::::::
ustreams-example.Disk.dbug
::::::::::::::
2012 203 09:10:26 A stdDbug message, first cached
2012 203 09:10:26 A stdDbug message, not cached
::::::::::::::
ustreams-example.Disk.err
::::::::::::::
2012 203 09:10:26 A stderr message, first cached
2012 203 09:10:26 A stderr message, not cached
::::::::::::::
ustreams-example.Disk.info
::::::::::::::
2012 203 09:10:26 A stdInfo message, first cached
2012 203 09:10:26 A stdInfo message, not cached
::::::::::::::
ustreams-example.Disk.log
::::::::::::::
2012 203 09:10:26 So this message, now, will not be seen in a normal terminal output,
2012 203 09:10:26 but in our disk-file instead.
2012 203 09:10:26 If you desire that stdout or stderr should continue sending to the terminal,
2012 203 09:10:26 you have the option to remove one or both from the ustreams_init() command.
2012 203 09:10:26 In this case, the U-Streams library will not intercept these streams.
2012 203 09:10:26 A stdout message, first cached
2012 203 09:10:26 Attempting connection to Database FOO
2012 203 09:10:26 Connection to DB FOO successful.
2012 203 09:10:26 A stdout message, not cached
::::::::::::::
ustreams-example.Disk.warn
::::::::::::::
2012 203 09:10:26 A stdWarn message, first cached
2012 203 09:10:26 A stdWarn message, not cached
::::::::::::::
ustreams-example.email.err
::::::::::::::
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stderr message, first cached
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stderr message, first cached
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stderr message, not cached
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stderr message, not cached
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stderr message, no longer delivered to Disk File
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stderr message, no longer delivered to Disk File
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Shutdown Msg
Message: Program ustreams-example has Completed and is Shutting Down.
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Shutdown Msg
Message: Program ustreams-example has Completed and is Shutting Down.
::::::::::::::
ustreams-example.email.warn
::::::::::::::
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stdWarn message, first cached
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stdWarn message, first cached
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stdWarn message, not cached
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stdWarn message, not cached
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stdWarn message, no longer delivered to Disk File
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Warning/Error
Message: A stdWarn message, no longer delivered to Disk File
To: alerts@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Shutdown Msg
Message: Program ustreams-example has Completed and is Shutting Down.
To: warnings@somecompany.com
From: ustreams-example proc
Subject: ustreams-example: Shutdown Msg
Message: Program ustreams-example has Completed and is Shutting Down.
Starting from $ 19.99
Questions & Comments
Leave a comment
Log-in now or register for a free account.
10 months ago
10 months ago
10 months ago