コード例 #1
0
ファイル: radtimers.c プロジェクト: mteel/radlib
//  ... decrement all timers; return shortest delta on list
static ULONG updateTimers (ULONG delta)
{
    register TIMER_ID   timer;
    ULONG               retVal = 0xFFFFFFFF;

    for (timer = (TIMER_ID) radListGetFirst (&timerList->pendingList);
         timer != NULL;
         timer = (TIMER_ID) radListGetNext (&timerList->pendingList, (NODE_PTR)timer))
    {
        if (timer->deltaTime <= delta)
        {
            timer->deltaTime = 0;
        }
        else
        {
            timer->deltaTime -= delta;
        }

        if (timer->deltaTime < retVal)
        {
            retVal = timer->deltaTime;
        }
    }

    return retVal;
}
コード例 #2
0
ファイル: alarms.c プロジェクト: breu/wview
static void pushLoopToClients(LOOP_PKT* loopData)
{
    WVIEW_ALARM_CLIENT  *client, *oldClient;
    LOOP_PKT            networkLoop;

    datafeedConvertLOOP_HTON(&networkLoop, loopData);

    // Push to each socket client:
    for (client = (WVIEW_ALARM_CLIENT *) radListGetFirst (&alarmsWork.clientList);
         client != NULL;
         client = (WVIEW_ALARM_CLIENT *) radListGetNext (&alarmsWork.clientList, 
                                                         (NODE_PTR)client))
    {
        // write the frame start so clients may sync to the beginning of each
        // data update
        if (radSocketWriteExact (client->client, 
                                 (void *)DF_LOOP_START_FRAME, 
                                 DF_START_FRAME_LENGTH)
            != DF_START_FRAME_LENGTH)
        {
            // write error, bail on this guy
            radMsgLog (PRI_HIGH, "LOOP: write error to client %s:%d - closing socket...",
                       radSocketGetHost (client->client),
                       radSocketGetPort (client->client));
            statusDecrementStat(ALARM_STATS_CLIENTS);
            radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(client->client));
            radSocketDestroy (client->client);
            oldClient = client;
            client = (WVIEW_ALARM_CLIENT *) 
                        radListGetPrevious (&alarmsWork.clientList, (NODE_PTR)client);
            radListRemove (&alarmsWork.clientList, (NODE_PTR)oldClient);
            free (oldClient);
            continue;
        }

        // write out the loop data in network byte order:
        if (radSocketWriteExact(client->client, &networkLoop, sizeof(networkLoop))
            != sizeof(networkLoop))
        {
            // write error, bail on this guy
            radMsgLog (PRI_HIGH, "LOOP: write error to client %s:%d - closing socket...",
                       radSocketGetHost (client->client),
                       radSocketGetPort (client->client));
            statusDecrementStat(ALARM_STATS_CLIENTS);
            radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(client->client));
            radSocketDestroy (client->client);
            oldClient = client;
            client = (WVIEW_ALARM_CLIENT *) 
                        radListGetPrevious (&alarmsWork.clientList, (NODE_PTR)client);
            radListRemove (&alarmsWork.clientList, (NODE_PTR)oldClient);
            free (oldClient);
            continue;
        }

        statusIncrementStat(ALARM_STATS_PKTS_SENT);
    }

    return;
}
コード例 #3
0
ファイル: sensor.c プロジェクト: HEnquist/wview
float sensorAccumGetTotal (WV_ACCUM_ID id)
{
    WV_ACCUM_SAMPLE*    nodePtr;
    float               sum = 0;

    // Do we need to age off any nodes?
    AgeAccumulator (id);

    for (nodePtr = (WV_ACCUM_SAMPLE*)radListGetFirst (&id->samples);
         nodePtr != NULL;
         nodePtr = (WV_ACCUM_SAMPLE*)radListGetNext (&id->samples, (NODE_PTR)nodePtr))
    {
        sum += nodePtr->value;
    }

    return sum;
}
コード例 #4
0
ファイル: alarms.c プロジェクト: breu/wview
static WVIEW_ALARM_CLIENT* FindClient(RADSOCK_ID clientSock)
{
    WVIEW_ALARM_CLIENT*     node;

    for (node = (WVIEW_ALARM_CLIENT*)radListGetFirst(&alarmsWork.clientList);
         node != NULL;
         node = (WVIEW_ALARM_CLIENT*)radListGetNext(&alarmsWork.clientList, (NODE_PTR)node))
    {
        if (node->client == clientSock)
        {
            // found him!
            return node;
        }
    }

    return NULL;
}
コード例 #5
0
ファイル: radtimers.c プロジェクト: mteel/radlib
int radTimerListDebug (void)
{
    register TIMER_ID   next;

    radMsgLog(PRI_HIGH, "################## radTimerListDebug START ##################");
    for (next = (TIMER_ID) radListGetFirst (&timerList->pendingList);
         next != NULL;
         next = (TIMER_ID) radListGetNext (&timerList->pendingList, (NODE_PTR)next))
    {
        if (next->routine)
        {
            radMsgLog(PRI_HIGH, "Timer-%8.8X: delta: %u, pending: %d, routine: %8.8X",
                       (ULONG)next, next->deltaTime, next->pending, (ULONG)next->routine);
        }
    }
    radMsgLog(PRI_HIGH, "################## radTimerListDebug  END  ##################");
}
コード例 #6
0
ファイル: raddatabase.c プロジェクト: mteel/radlib
/*  ... get the field of interest; returns FIELD_ID or NULL
*/
FIELD_ID raddatabaseFieldGet
(
    ROW_ID          id,
    const char      *fieldName
)
{
    FIELD_ID        field;

    for (field = (FIELD_ID) radListGetFirst (&id->fields);
         field != NULL;
         field = (FIELD_ID) radListGetNext (&id->fields, (NODE_PTR)field))
    {
        if (!strcasecmp (field->name, fieldName))
        {
            return field;
        }
    }

    return NULL;
}
コード例 #7
0
ファイル: alarms.c プロジェクト: breu/wview
static void RemoveClient(RADSOCK_ID clientSock)
{
    WVIEW_ALARM_CLIENT*     node;

    for (node = (WVIEW_ALARM_CLIENT*)radListGetFirst(&alarmsWork.clientList);
         node != NULL;
         node = (WVIEW_ALARM_CLIENT*)radListGetNext(&alarmsWork.clientList, (NODE_PTR)node))
    {
        if (node->client == clientSock)
        {
            // found him!
            statusDecrementStat(ALARM_STATS_CLIENTS);
            radListRemove(&alarmsWork.clientList, (NODE_PTR)node);
            radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(node->client));
            radSocketDestroy(node->client);
            free(node);
            return;
        }
    }
}
コード例 #8
0
ファイル: alarms.c プロジェクト: breu/wview
static void pushArchiveToClients(ARCHIVE_PKT* archive)
{
    WVIEW_ALARM_CLIENT  *client, *oldClient;
    ARCHIVE_PKT         networkArchive;

    datafeedConvertArchive_HTON(&networkArchive, archive);

    // Push to each socket client:
    for (client = (WVIEW_ALARM_CLIENT *) radListGetFirst (&alarmsWork.clientList);
         client != NULL;
         client = (WVIEW_ALARM_CLIENT *) radListGetNext (&alarmsWork.clientList, 
                                                         (NODE_PTR)client))
    {
        // Check for archive sync in progress:
        if (client->syncInProgress)
        {
            continue;
        }

        // Write start frame and archive packet on the socket:
        if (WriteArchiveToClient(client->client, &networkArchive) == ERROR)
        {
            // write error, bail on this guy
            radMsgLog (PRI_HIGH, "ARCHIVE: write error to client %s:%d - closing socket...",
                       radSocketGetHost (client->client),
                       radSocketGetPort (client->client));
            statusDecrementStat(ALARM_STATS_CLIENTS);
            radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(client->client));
            radSocketDestroy (client->client);
            oldClient = client;
            client = (WVIEW_ALARM_CLIENT *) 
                        radListGetPrevious (&alarmsWork.clientList, (NODE_PTR)client);
            radListRemove (&alarmsWork.clientList, (NODE_PTR)oldClient);
            free (oldClient);
            continue;
        }
    }

    return;
}
コード例 #9
0
ファイル: radtimers.c プロジェクト: mteel/radlib
//  ... process expired timers
static void processExpiredTimers (void)
{
    register TIMER_ID   timer, prevTimer;
    SYS_CALLBACK_MSG    cbMsg;
    int                 retVal;

    for (timer = (TIMER_ID) radListGetFirst (&timerList->pendingList);
         timer != NULL;
         timer = (TIMER_ID) radListGetNext (&timerList->pendingList, (NODE_PTR)timer))
    {
        if (timer->deltaTime == 0)
        {
            // remove from pending list
            prevTimer = (TIMER_ID) radListGetPrevious (&timerList->pendingList, (NODE_PTR)timer);
            radListRemove (&timerList->pendingList, (NODE_PTR)timer);

            timer->pending = FALSE;

            // send expiry notification
            if (timer->routine != NULL)
            {
                cbMsg.length    = sizeof (cbMsg) - sizeof (cbMsg.length);
                cbMsg.msgType   = 0;
                cbMsg.callback  = timer->routine;
                cbMsg.parm      = timer->parm;
                retVal = write (timerList->notifyFD, &cbMsg, sizeof (cbMsg));
                if (retVal != sizeof (cbMsg))
                {
                    radMsgLog(PRI_HIGH, "processExpiredTimers: write to notify fd failed: %s",
                               strerror (errno));
                }
            }

            timer = prevTimer;
        }
    }

    return;
}
コード例 #10
0
ファイル: raddatabase.c プロジェクト: mteel/radlib
ROW_ID raddatabaseResultsGetNext (RESULT_SET_ID id)
{
    id->current = (ROW_ID)radListGetNext (&id->rows, (NODE_PTR)id->current);
    return id->current;
}
コード例 #11
0
ファイル: htmlMgr.c プロジェクト: HEnquist/wview
int htmlmgrGenerate
(
    HTML_MGR_ID         id
)
{
    register HTML_IMG   *img;
    int                 retVal, imgs = 0, htmls = 0;
    char                temp[256];
    struct stat         fileData;

    GenerateTime = radTimeGetMSSinceEpoch ();

#if __DEBUG_BUFFERS
    radMsgLog (PRI_STATUS, "DBG BFRS: HTML BEGIN: %u of %u available",
               buffersGetAvailable (),
               buffersGetTotal ());
#endif

    //  ... compute the Barometric Pressure trend
    computeBPTrend (id);

#if DEBUG_GENERATION
    radMsgLog (PRI_MEDIUM, "GENERATE: images");
#endif

    //  ... generate the weather images
    for (img = (HTML_IMG *)radListGetFirst (&id->imgList);
         img != NULL;
         img = (HTML_IMG *)radListGetNext (&id->imgList, (NODE_PTR)img))
    {
        retVal = (*img->generator) (img);
        if (retVal == OK)
        {
            imgs ++;
        }
        else if (retVal != ERROR_ABORT)
        {
            sprintf (temp, "%s/%s", id->imagePath, img->fname);
            radMsgLog (PRI_HIGH, "%s generation failed - must be local to the wview server!",
                       temp);
            radMsgLog (PRI_HIGH, "Otherwise you may be including data in "
                                 "images.conf for which you do not have sensors?!?");
        }
    }

    //  ... clear the archiveAvailable flag (must be after generator loop)
    id->newArchiveMask = 0;

#if DEBUG_GENERATION
    radMsgLog (PRI_MEDIUM, "GENERATE: pre-generate script");
#endif

    // If the wview pre-generation script exists, run it now
    sprintf (temp, "%s/%s", WVIEW_CONFIG_DIR, HTML_PRE_GEN_SCRIPT);
    if (stat (temp, &fileData) == 0)
    {
        // File exists, run it
        radStartProcess (newProcessEntryPoint, temp);
    }

#if DEBUG_GENERATION
    radMsgLog (PRI_MEDIUM, "GENERATE: templates");
#endif

    //  ... now generate the HTML
    if ((htmls = htmlgenOutputFiles(id, GenerateTime)) == ERROR)
    {
        return ERROR;
    }

    wvutilsLogEvent(PRI_STATUS, "Generated: %u ms: %d images, %d template files",
                    (uint32_t)(radTimeGetMSSinceEpoch() - GenerateTime), imgs, htmls);

    id->imagesGenerated += imgs;
    id->templatesGenerated += htmls;
    statusUpdateStat(HTML_STATS_IMAGES_GENERATED, id->imagesGenerated);
    statusUpdateStat(HTML_STATS_TEMPLATES_GENERATED, id->templatesGenerated);

#if __DEBUG_BUFFERS
    radMsgLog (PRI_STATUS, "DBG BFRS: HTML END: %u of %u available",
               buffersGetAvailable (),
               buffersGetTotal ());
#endif

#if DEBUG_GENERATION
    radMsgLog (PRI_MEDIUM, "GENERATE: post-generate script");
#endif

    // Finally, if the wview post-generation script exists, run it now
    sprintf (temp, "%s/%s", WVIEW_CONFIG_DIR, HTML_POST_GEN_SCRIPT);
    if (stat (temp, &fileData) == 0)
    {
        // File exists, run it
        radStartProcess (newProcessEntryPoint, temp);
    }

#if DEBUG_GENERATION
    radMsgLog (PRI_MEDIUM, "GENERATE: DONE");
#endif

    return OK;
}
コード例 #12
0
ファイル: alarms.c プロジェクト: breu/wview
static void processAlarms (LOOP_PKT *loopData)
{
    WVIEW_ALARM         *alarm;
    float               tempFloat;

    // process the local alarms:
    for (alarm = (WVIEW_ALARM *) radListGetFirst (&alarmsWork.alarmList);
         alarm != NULL;
         alarm = (WVIEW_ALARM *) radListGetNext (&alarmsWork.alarmList, 
                                                 (NODE_PTR)alarm))
    {
        // first check to see if we are in abatement
        if (alarm->triggered)
        {
            if ((radTimeGetSECSinceEpoch () - alarm->abateStart) < alarm->abateSecs)
            {
                // abatement - go to the next alarm
                continue;
            }
            else
            {
                // clear trigger for future alarms
                alarm->triggered = FALSE;
            }
        }

        // switch on alarm type
        switch (alarm->type)
        {
            case Barometer:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertINHGToHPA(loopData->barometer);
                }
                else
                {
                    tempFloat = loopData->barometer;
                }
                break;

            case InsideTemp:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->inTemp);
                }
                else
                {
                    tempFloat = loopData->inTemp;
                }
                break;

            case InsideHumidity:
                tempFloat = (float)loopData->inHumidity;
                break;

            case OutsideTemp:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->outTemp);
                }
                else
                {
                    tempFloat = loopData->outTemp;
                }
                break;

            case WindSpeed:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertMPHToKPH((float)loopData->windSpeed);
                }
                else
                {
                    tempFloat = (float)loopData->windSpeed;
                }
                break;

            case TenMinuteAvgWindSpeed:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertMPHToKPH((float)loopData->tenMinuteAvgWindSpeed);
                }
                else
                {
                    tempFloat = (float)loopData->tenMinuteAvgWindSpeed;
                }
                break;

            case WindDirection:
                tempFloat = (float)loopData->windDir;
                break;

            case OutsideHumidity:
                tempFloat = (float)loopData->outHumidity;
                break;

            case RainRate:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->rainRate);
                }
                else
                {
                    tempFloat = loopData->rainRate;
                }
                break;

            case StormRain:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->stormRain);
                }
                else
                {
                    tempFloat = loopData->stormRain;
                }
                break;

            case DayRain:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->dayRain);
                }
                else
                {
                    tempFloat = loopData->dayRain;
                }
                break;

            case MonthRain:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->monthRain);
                }
                else
                {
                    tempFloat = loopData->monthRain;
                }
                break;

            case YearRain:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->yearRain);
                }
                else
                {
                    tempFloat = loopData->yearRain;
                }
                break;

            case TxBatteryStatus:
                tempFloat = (float)loopData->txBatteryStatus;
                break;

            case ConsoleBatteryVoltage:
                tempFloat = (((float)loopData->consBatteryVoltage * 300)/512)/100;
                break;

            case DewPoint:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->dewpoint);
                }
                else
                {
                    tempFloat = loopData->dewpoint;
                }
                break;

            case WindChill:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->windchill);
                }
                else
                {
                    tempFloat = loopData->windchill;
                }
                break;

            case HeatIndex:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->heatindex);
                }
                else
                {
                    tempFloat = loopData->heatindex;
                }
                break;

            case Radiation:
                tempFloat = (float)loopData->radiation;
                break;

            case UV:
                tempFloat = (float)loopData->UV;
                break;

            case ET:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->dayET);
                }
                else
                {
                    tempFloat = loopData->dayET;
                }
                break;

            case ExtraTemp1:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->extraTemp1);
                }
                else
                {
                    tempFloat = loopData->extraTemp1;
                }
                break;

            case ExtraTemp2:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->extraTemp2);
                }
                else
                {
                    tempFloat = loopData->extraTemp2;
                }
                break;

            case ExtraTemp3:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->extraTemp3);
                }
                else
                {
                    tempFloat = loopData->extraTemp3;
                }
                break;

            case SoilTemp1:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->soilTemp1);
                }
                else
                {
                    tempFloat = loopData->soilTemp1;
                }
                break;

            case SoilTemp2:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->soilTemp2);
                }
                else
                {
                    tempFloat = loopData->soilTemp2;
                }
                break;

            case SoilTemp3:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->soilTemp3);
                }
                else
                {
                    tempFloat = loopData->soilTemp3;
                }
                break;

            case SoilTemp4:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->soilTemp4);
                }
                else
                {
                    tempFloat = loopData->soilTemp4;
                }
                break;

            case LeafTemp1:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->leafTemp1);
                }
                else
                {
                    tempFloat = loopData->leafTemp1;
                }
                break;

            case LeafTemp2:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->leafTemp2);
                }
                else
                {
                    tempFloat = loopData->leafTemp2;
                }
                break;

            case ExtraHumid1:
                tempFloat = (float)loopData->extraHumid1;
                break;

            case ExtraHumid2:
                tempFloat = (float)loopData->extraHumid2;
                break;

            case Wxt510Hail:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->wxt510Hail);
                }
                else
                {
                    tempFloat = loopData->wxt510Hail;
                }
                break;

            case Wxt510Hailrate:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertRainINToMetric(loopData->wxt510Hailrate);
                }
                else
                {
                    tempFloat = loopData->wxt510Hailrate;
                }
                break;

            case Wxt510HeatingTemp:
                if (alarmsWork.isMetric)
                {
                    tempFloat = wvutilsConvertFToC(loopData->wxt510HeatingTemp);
                }
                else
                {
                    tempFloat = loopData->wxt510HeatingTemp;
                }
                break;

            case Wxt510HeatingVoltage:
                tempFloat = loopData->wxt510HeatingVoltage;
                break;

            case Wxt510SupplyVoltage:
                tempFloat = loopData->wxt510SupplyVoltage;
                break;

            case Wxt510ReferenceVoltage:
                tempFloat = loopData->wxt510ReferenceVoltage;
                break;

            default:
                // no match, blow it off
                continue;
        }

        // see if we tripped the breaker here
        if (alarm->isMax)
        {
            if (tempFloat >= alarm->bound)
            {
                // we did!
                alarm->triggered = TRUE;
                alarm->triggerValue = tempFloat;
                alarm->abateStart = radTimeGetSECSinceEpoch ();

                // run user script here
                statusIncrementStat(ALARM_STATS_SCRIPTS_RUN);
                if (executeScript (alarm) != 0)
                {
                    radMsgLog (PRI_MEDIUM, 
                               "processAlarms: script %s failed",
                               alarm->scriptToRun);
                }
            }
        }
        else
        {
            if (tempFloat <= alarm->bound)
            {
                // we did!
                alarm->triggered = TRUE;
                alarm->triggerValue = tempFloat;
                alarm->abateStart = radTimeGetSECSinceEpoch ();

                // run user script here
                statusIncrementStat(ALARM_STATS_SCRIPTS_RUN);
                if (executeScript (alarm) != 0)
                {
                    radMsgLog (PRI_MEDIUM, 
                               "processAlarms: script %s failed",
                               alarm->scriptToRun);
                }
            }
        }
    }

    return;
}
コード例 #13
0
ファイル: alarms.c プロジェクト: breu/wview
/*  ... the main entry point for the alarm process
*/
int main (int argc, char *argv[])
{
    void            (*alarmHandler)(int);
    int             retVal;
    FILE            *pidfile;
    WVIEW_ALARM     *alarm;
    int             runAsDaemon = TRUE;

    if (argc > 1)
    {
        if (!strcmp(argv[1], "-f"))
        {
            runAsDaemon = FALSE;
        }
    }

    memset (&alarmsWork, 0, sizeof (alarmsWork));
    radListReset (&alarmsWork.alarmList);
    radListReset (&alarmsWork.clientList);

    /*  ... initialize some system stuff first
    */
    retVal = alarmsSysInit (&alarmsWork);
    if (retVal == ERROR)
    {
        radMsgLogInit (PROC_NAME_ALARMS, FALSE, TRUE);
        radMsgLog (PRI_CATASTROPHIC, "wvalarmd sysinit failed!");
        radMsgLogExit ();
        exit (1);
    }
    else if (retVal == ERROR_ABORT)
    {
        exit (2);
    }


    /*  ... call the global radlib system init function
    */
    if (radSystemInit (WVIEW_SYSTEM_ID) == ERROR)
    {
        radMsgLogInit (PROC_NAME_ALARMS, TRUE, TRUE);
        radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!");
        radMsgLogExit ();
        exit (1);
    }


    /*  ... call the radlib process init function
    */
    if (radProcessInit (PROC_NAME_ALARMS,
                        alarmsWork.fifoFile,
                        PROC_NUM_TIMERS_ALARMS,
                        runAsDaemon,                // TRUE for daemon
                        msgHandler,
                        evtHandler,
                        NULL)
        == ERROR)
    {
        printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_ALARMS);
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    alarmsWork.myPid = getpid ();
    pidfile = fopen (alarmsWork.pidFile, "w");
    if (pidfile == NULL)
    {
        radMsgLog (PRI_CATASTROPHIC, "lock file create failed!");
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    fprintf (pidfile, "%d", getpid ());
    fclose (pidfile);

    alarmHandler = radProcessSignalGetHandler (SIGALRM);
    radProcessSignalCatchAll (defaultSigHandler);
    radProcessSignalCatch (SIGALRM, alarmHandler);
    radProcessSignalRelease(SIGABRT);


    // grab all of our alarm definitions from the config database
    retVal = readAlarmsConfig ();
    if (retVal == ERROR_ABORT)
    {
        radMsgLog (PRI_HIGH, "ALARM daemon not enabled - exiting...");
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (0);
    }
    else if (retVal < 0)
    {
        radMsgLog (PRI_HIGH, "readAlarmsConfig failed - "
                   "is there a problem with the wview config database?");
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        radMsgLog (PRI_STATUS, 
                   "alarms: added %d alarm definitions",
                   retVal);
    }

    if (statusInit(alarmsWork.statusFile, alarmsStatusLabels) == ERROR)
    {
        radMsgLog (PRI_HIGH, "ALARM status init failed - exiting...");
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    statusUpdate(STATUS_BOOTING);
    statusUpdateStat(ALARM_STATS_ALARMS, retVal);


    // wait a bit here before continuing
    radUtilsSleep (500);


    //  register with the radlib message router
    if (radMsgRouterInit (WVIEW_RUN_DIR) == ERROR)
    {
        statusUpdateMessage("radMsgRouterInit failed!");
        radMsgLog (PRI_HIGH, "radMsgRouterInit failed!");
        statusUpdate(STATUS_ERROR);
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // enable message reception from the radlib router for SHUTDOWN msgs
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_SHUTDOWN);

    // wait for the wview daemon to be ready
    if (waitForWviewDaemon () == ERROR)
    {
        radMsgLog (PRI_HIGH, "waitForWviewDaemon failed");
        statusUpdate(STATUS_ERROR);
        radMsgRouterExit ();
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // finally, initialize our data feed socket
    alarmsWork.dataFeedServer = radSocketServerCreate(WV_DATAFEED_PORT);
    if (alarmsWork.dataFeedServer == NULL)
    {
        statusUpdateMessage("radSocketServerCreate failed");
        radMsgLog (PRI_HIGH, "radSocketServerCreate failed...");
        statusUpdate(STATUS_ERROR);
        radMsgRouterExit ();
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // add it to our descriptors of interest
    if (radProcessIORegisterDescriptor(radSocketGetDescriptor(alarmsWork.dataFeedServer),
                                       dataFeedAccept,
                                       NULL)
        == ERROR)
    {
        statusUpdateMessage("radProcessIORegisterDescriptor server failed");
        radMsgLog (PRI_HIGH, "radProcessIORegisterDescriptor failed...");
        statusUpdate(STATUS_ERROR);
        radSocketDestroy (alarmsWork.dataFeedServer);
        radMsgRouterExit ();
        alarmsSysExit (&alarmsWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // enable message reception from the radlib router for loop data
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_LOOP_DATA_SVC);

    // enable message reception from the radlib router for archive data
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_ARCHIVE_DATA);

    // enable message reception from the radlib router for POLL msgs
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_POLL);


    // enter normal processing
    alarmsWork.inMainLoop = TRUE;
    statusUpdate(STATUS_RUNNING);
    statusUpdateMessage("Normal operation");
    radMsgLog (PRI_STATUS, "running...");


    // Do we need to trigger a test alarm?
    if (alarmsWork.doTest)
    {
        if (1 <= alarmsWork.doTestNumber && alarmsWork.doTestNumber <= ALARMS_MAX)
        {
            // Generate the bad boy:
            retVal = 1;
            for (alarm = (WVIEW_ALARM *) radListGetFirst (&alarmsWork.alarmList);
                 retVal <= ALARMS_MAX && alarm != NULL;
                 alarm = (WVIEW_ALARM *) radListGetNext (&alarmsWork.alarmList, 
                                                         (NODE_PTR)alarm))
            {
                if (retVal == alarmsWork.doTestNumber)
                {
                    // This is the one to test:
                    alarm->triggerValue = -1;

                    // run user script here
                    if (executeScript(alarm) != 0)
                    {
                        radMsgLog (PRI_MEDIUM, 
                                   "Test Alarm %d: script %s failed",
                                   retVal, alarm->scriptToRun);
                    }
                    else
                    {
                        radMsgLog (PRI_MEDIUM, 
                                   "Test Alarm %d: script %s executed",
                                   retVal, alarm->scriptToRun);
                    }
                    retVal = ALARMS_MAX;
                }

                retVal ++;
            }
        }
        else
        {
            radMsgLog (PRI_MEDIUM, "Test Alarm: bad alarm index %d given!",
                       alarmsWork.doTestNumber);
        }
    }


    while (!alarmsWork.exiting)
    {
        // wait on something interesting
        if (radProcessWait (0) == ERROR)
        {
            alarmsWork.exiting = TRUE;
        }
    }


    statusUpdateMessage("exiting normally");
    radMsgLog (PRI_STATUS, "exiting normally...");
    statusUpdate(STATUS_SHUTDOWN);

    radSocketDestroy (alarmsWork.dataFeedServer);
    radMsgRouterExit ();
    alarmsSysExit (&alarmsWork);
    radProcessExit ();
    radSystemExit (WVIEW_SYSTEM_ID);
    exit (0);
}