506 lines
17 KiB
C
506 lines
17 KiB
C
/* $NetBSD: rf_demo.c,v 1.1 1998/11/13 04:20:28 oster Exp $ */
|
|
/*
|
|
* Copyright (c) 1995 Carnegie-Mellon University.
|
|
* All rights reserved.
|
|
*
|
|
* Author: Mark Holland, Khalil Amiri
|
|
*
|
|
* Permission to use, copy, modify and distribute this software and
|
|
* its documentation is hereby granted, provided that both the copyright
|
|
* notice and this permission notice appear in all copies of the
|
|
* software, derivative works or modified versions, and any portions
|
|
* thereof, and that both notices appear in supporting documentation.
|
|
*
|
|
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
|
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
|
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
|
*
|
|
* Carnegie Mellon requests users of this software to return to
|
|
*
|
|
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
|
* School of Computer Science
|
|
* Carnegie Mellon University
|
|
* Pittsburgh PA 15213-3890
|
|
*
|
|
* any improvements or extensions that they make and grant Carnegie the
|
|
* rights to redistribute these changes.
|
|
*/
|
|
|
|
/**********************************************************************************
|
|
*
|
|
* rf_demo.c -- code for supporting demos. this is not actually part of the driver.
|
|
*
|
|
**********************************************************************************/
|
|
|
|
/* :
|
|
* Log: rf_demo.c,v
|
|
* Revision 1.24 1996/06/17 14:38:33 jimz
|
|
* properly #if out RF_DEMO code
|
|
* fix bug in MakeConfig that was causing weird behavior
|
|
* in configuration routines (config was not zeroed at start)
|
|
* clean up genplot handling of stacks
|
|
*
|
|
* Revision 1.23 1996/06/17 03:23:09 jimz
|
|
* explicitly do pthread stuff (for join)
|
|
* NOTE: this should be changed!
|
|
*
|
|
* Revision 1.22 1996/06/14 23:15:38 jimz
|
|
* attempt to deal with thread GC problem
|
|
*
|
|
* Revision 1.21 1996/06/09 02:36:46 jimz
|
|
* lots of little crufty cleanup- fixup whitespace
|
|
* issues, comment #ifdefs, improve typing in some
|
|
* places (esp size-related)
|
|
*
|
|
* Revision 1.20 1996/06/05 18:06:02 jimz
|
|
* Major code cleanup. The Great Renaming is now done.
|
|
* Better modularity. Better typing. Fixed a bunch of
|
|
* synchronization bugs. Made a lot of global stuff
|
|
* per-desc or per-array. Removed dead code.
|
|
*
|
|
* Revision 1.19 1996/05/30 23:22:16 jimz
|
|
* bugfixes of serialization, timing problems
|
|
* more cleanup
|
|
*
|
|
* Revision 1.18 1996/05/30 11:29:41 jimz
|
|
* Numerous bug fixes. Stripe lock release code disagreed with the taking code
|
|
* about when stripes should be locked (I made it consistent: no parity, no lock)
|
|
* There was a lot of extra serialization of I/Os which I've removed- a lot of
|
|
* it was to calculate values for the cache code, which is no longer with us.
|
|
* More types, function, macro cleanup. Added code to properly quiesce the array
|
|
* on shutdown. Made a lot of stuff array-specific which was (bogusly) general
|
|
* before. Fixed memory allocation, freeing bugs.
|
|
*
|
|
* Revision 1.17 1996/05/27 18:56:37 jimz
|
|
* more code cleanup
|
|
* better typing
|
|
* compiles in all 3 environments
|
|
*
|
|
* Revision 1.16 1996/05/23 00:33:23 jimz
|
|
* code cleanup: move all debug decls to rf_options.c, all extern
|
|
* debug decls to rf_options.h, all debug vars preceded by rf_
|
|
*
|
|
* Revision 1.15 1996/05/20 16:14:08 jimz
|
|
* switch to rf_{mutex,cond}_{init,destroy}
|
|
*
|
|
* Revision 1.14 1996/05/18 19:51:34 jimz
|
|
* major code cleanup- fix syntax, make some types consistent,
|
|
* add prototypes, clean out dead code, et cetera
|
|
*
|
|
* Revision 1.13 1995/12/01 15:56:07 root
|
|
* added copyright info
|
|
*
|
|
*/
|
|
|
|
#include "rf_archs.h"
|
|
|
|
#if RF_DEMO > 0
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <strings.h>
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
#include <signal.h>
|
|
|
|
#include "rf_threadstuff.h"
|
|
#include "rf_demo.h"
|
|
#include "rf_utils.h"
|
|
#include "rf_general.h"
|
|
#include "rf_options.h"
|
|
|
|
#ifdef SIMULATE
|
|
#include "rf_diskevent.h"
|
|
#endif /* SIMULATE */
|
|
|
|
static int doMax = 0; /* currently no way to set this */
|
|
|
|
/****************************************************************************************
|
|
* fault-free demo code
|
|
***************************************************************************************/
|
|
|
|
static int user_iops_meter = -1;
|
|
static int disk_iops_meter = -1;
|
|
static int max_user_meter = -1;
|
|
static int max_disk_meter = -1;
|
|
static int recon_pctg_meter = -1;
|
|
static int avg_resp_time_meter = -1;
|
|
static int recon_time_meter = -1;
|
|
static int ff_avg_resp_time_meter = -1;
|
|
static int deg_avg_resp_time_meter = -1;
|
|
static int recon_avg_resp_time_meter = -1;
|
|
static int user_ios_ff=0;
|
|
static int user_ios_deg=0;
|
|
static int user_ios_recon=0;
|
|
static long user_resp_time_sum_ff = 0;
|
|
static long user_resp_time_sum_deg = 0;
|
|
static long user_resp_time_sum_recon = 0;
|
|
|
|
int rf_demo_op_mode = 0;
|
|
|
|
RF_DECLARE_STATIC_MUTEX(iops_mutex)
|
|
static int user_ios_so_far, disk_ios_so_far, max_user, max_disk;
|
|
static long user_resp_time_sum_ms;
|
|
static int recon_pctg;
|
|
static struct timeval iops_starttime;
|
|
#ifndef SIMULATE
|
|
static RF_Thread_t update_thread_desc;
|
|
#endif /* !SIMULATE */
|
|
static int meter_update_terminate;
|
|
|
|
static int meter_update_interval = 2; /* seconds between meter updates */
|
|
static int iops_initialized = 0, recon_initialized = 0;
|
|
|
|
static char *demoMeterTags[] = {"FF", "Degr", "Recon"};
|
|
|
|
static int vpos=0;
|
|
|
|
static int rf_CreateMeter(char *title, char *geom, char *color);
|
|
static void rf_UpdateMeter(int meterid, int value);
|
|
static void rf_DestroyMeter(int meterid, int killproc);
|
|
|
|
void rf_startup_iops_demo(meter_vpos, C, G)
|
|
int meter_vpos;
|
|
int C;
|
|
int G;
|
|
{
|
|
char buf[100], title[100];
|
|
int rc;
|
|
|
|
vpos = meter_vpos;
|
|
sprintf(buf, "%dx%d-0+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"%s %d/%d User IOs/sec",demoMeterTags[rf_demoMeterTag],C,G);
|
|
user_iops_meter = rf_CreateMeter(title, buf, "black");
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING,vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"%s %d/%d Disk IOs/sec",demoMeterTags[rf_demoMeterTag],C,G);
|
|
disk_iops_meter = rf_CreateMeter(title, buf, "red");
|
|
if (doMax) {
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, 2*(RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING),vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"%s %d/%d Avg User IOs/s",demoMeterTags[rf_demoMeterTag],C,G);
|
|
max_user_meter = rf_CreateMeter(title, buf, "black");
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, 3*(RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"%s %d/%d Avg Disk IOs/s",demoMeterTags[rf_demoMeterTag],C,G);
|
|
max_disk_meter = rf_CreateMeter(title, buf, "red");
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, 4*(RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
} else {
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, 2*(RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
}
|
|
sprintf(title,"%s %d/%d Avg User Resp Time (ms)",demoMeterTags[rf_demoMeterTag],C,G);
|
|
avg_resp_time_meter = rf_CreateMeter(title, buf, "blue");
|
|
rc = rf_mutex_init(&iops_mutex);
|
|
if (rc) {
|
|
RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
|
|
__LINE__, rc);
|
|
return;
|
|
}
|
|
user_ios_so_far = disk_ios_so_far = max_user = max_disk = 0;
|
|
user_resp_time_sum_ms = 0;
|
|
|
|
meter_update_terminate = 0;
|
|
#ifndef SIMULATE
|
|
pthread_create(&update_thread_desc, raidframe_attr_default, (pthread_startroutine_t)rf_meter_update_thread, NULL);
|
|
#endif /* !SIMULATE */
|
|
gettimeofday(&iops_starttime, NULL);
|
|
iops_initialized = 1;
|
|
}
|
|
|
|
|
|
void rf_update_user_stats(resptime)
|
|
int resptime;
|
|
{
|
|
if (!iops_initialized && !recon_initialized) return;
|
|
RF_LOCK_MUTEX(iops_mutex);
|
|
user_ios_so_far++;
|
|
user_resp_time_sum_ms += resptime;
|
|
RF_UNLOCK_MUTEX(iops_mutex);
|
|
}
|
|
|
|
void rf_update_disk_iops(val)
|
|
int val;
|
|
{
|
|
if (!iops_initialized) return;
|
|
RF_LOCK_MUTEX(iops_mutex);
|
|
disk_ios_so_far += val;
|
|
RF_UNLOCK_MUTEX(iops_mutex);
|
|
}
|
|
|
|
void rf_meter_update_thread()
|
|
{
|
|
struct timeval now, diff;
|
|
int iops, resptime;
|
|
float secs;
|
|
|
|
#ifndef SIMULATE
|
|
while (!meter_update_terminate) {
|
|
gettimeofday(&now, NULL);
|
|
RF_TIMEVAL_DIFF(&iops_starttime, &now, &diff);
|
|
secs = ((float) diff.tv_sec) + ((float) diff.tv_usec)/1000000.0;
|
|
#else /* !SIMULATE */
|
|
secs = rf_cur_time;
|
|
#endif /* !SIMULATE */
|
|
if (user_iops_meter >= 0) {
|
|
iops = (secs!=0.0) ? (int) (((float) user_ios_so_far) / secs) : 0;
|
|
rf_UpdateMeter(user_iops_meter, iops);
|
|
if (max_user_meter && iops > max_user) {max_user = iops; rf_UpdateMeter(max_user_meter, iops);}
|
|
}
|
|
|
|
if (disk_iops_meter >= 0) {
|
|
iops = (secs!=0.0) ? (int) (((float) disk_ios_so_far) / secs) : 0;
|
|
rf_UpdateMeter(disk_iops_meter, iops);
|
|
if (max_disk_meter && iops > max_disk) {max_disk = iops; rf_UpdateMeter(max_disk_meter, iops);}
|
|
}
|
|
|
|
if (recon_pctg_meter >= 0) {
|
|
rf_UpdateMeter(recon_pctg_meter, recon_pctg);
|
|
}
|
|
|
|
switch (rf_demo_op_mode){
|
|
case RF_DEMO_FAULT_FREE:
|
|
resptime = (user_ios_so_far != 0) ? user_resp_time_sum_ms / user_ios_so_far : 0;
|
|
if (resptime && (ff_avg_resp_time_meter >=0))
|
|
rf_UpdateMeter(ff_avg_resp_time_meter, resptime);
|
|
user_ios_ff += user_ios_so_far;
|
|
user_resp_time_sum_ff += user_resp_time_sum_ms;
|
|
break;
|
|
case RF_DEMO_DEGRADED:
|
|
resptime = (user_ios_so_far != 0) ? user_resp_time_sum_ms / user_ios_so_far : 0;
|
|
if (resptime &&(deg_avg_resp_time_meter >=0))
|
|
rf_UpdateMeter(deg_avg_resp_time_meter, resptime);
|
|
user_ios_deg += user_ios_so_far;
|
|
user_resp_time_sum_deg += user_resp_time_sum_ms;
|
|
case RF_DEMO_RECON:
|
|
resptime = (user_ios_so_far != 0) ? user_resp_time_sum_ms / user_ios_so_far : 0;
|
|
if (resptime && (recon_avg_resp_time_meter >= 0))
|
|
rf_UpdateMeter(recon_avg_resp_time_meter, resptime);
|
|
user_ios_recon += user_ios_so_far;
|
|
user_resp_time_sum_recon += user_resp_time_sum_ms;
|
|
break;
|
|
default: printf("WARNING: demo meter update thread: Invalid op mode! \n");
|
|
}
|
|
user_ios_so_far = 0;
|
|
user_resp_time_sum_ms = 0;
|
|
#ifndef SIMULATE
|
|
RF_DELAY_THREAD(1,0);
|
|
}
|
|
#endif /* !SIMULATE */
|
|
}
|
|
|
|
void rf_finish_iops_demo()
|
|
{
|
|
long status;
|
|
|
|
if (!iops_initialized) return;
|
|
iops_initialized = 0; /* make sure any subsequent update calls don't do anything */
|
|
meter_update_terminate = 1;
|
|
#ifndef SIMULATE
|
|
pthread_join(update_thread_desc, (pthread_addr_t)&status);
|
|
#endif /* !SIMULATE */
|
|
|
|
rf_DestroyMeter(user_iops_meter, (doMax) ? 1 : 0);
|
|
rf_DestroyMeter(disk_iops_meter, (doMax) ? 1 : 0);
|
|
rf_DestroyMeter(max_user_meter, 0);
|
|
rf_DestroyMeter(max_disk_meter, 0);
|
|
rf_DestroyMeter(avg_resp_time_meter, 0);
|
|
rf_mutex_destroy(&iops_mutex);
|
|
}
|
|
|
|
void rf_demo_update_mode(arg_mode)
|
|
int arg_mode;
|
|
{
|
|
int hpos;
|
|
char buf[100], title[100];
|
|
|
|
switch (rf_demo_op_mode = arg_mode) {
|
|
case RF_DEMO_DEGRADED:
|
|
|
|
/* freeze fault-free response time meter; create degraded mode meter */
|
|
hpos=rf_demoMeterHpos+2;
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, hpos * (RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"Degraded Mode Average Response Time (ms)",demoMeterTags[rf_demoMeterTag]);
|
|
deg_avg_resp_time_meter = rf_CreateMeter(title, buf, "purple");
|
|
rf_UpdateMeter(ff_avg_resp_time_meter, (user_ios_ff == 0)? 0: user_resp_time_sum_ff/user_ios_ff);
|
|
break;
|
|
|
|
case RF_DEMO_RECON:
|
|
|
|
/* freeze degraded mode response time meter; create recon meters */
|
|
hpos = rf_demoMeterHpos+1;
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, hpos * (RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"Reconstruction Average Response Time (ms)",demoMeterTags[rf_demoMeterTag]);
|
|
recon_avg_resp_time_meter = rf_CreateMeter(title, buf, "darkgreen");
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, (rf_demoMeterHpos) * (RF_DEMO_METER_WIDTH + RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"Percent Complete / Recon Time");
|
|
recon_pctg_meter = rf_CreateMeter(title,buf,"red");
|
|
rf_UpdateMeter(deg_avg_resp_time_meter, (user_ios_deg == 0)? 0: user_resp_time_sum_deg/user_ios_deg);
|
|
break;
|
|
|
|
default: /*do nothing -- finish_recon_demo will update rest of meters */;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************************
|
|
* reconstruction demo code
|
|
***************************************************************************************/
|
|
|
|
|
|
void rf_startup_recon_demo(meter_vpos, C, G, init)
|
|
int meter_vpos;
|
|
int C;
|
|
int G;
|
|
int init;
|
|
{
|
|
char buf[100], title[100];
|
|
int rc;
|
|
|
|
vpos = meter_vpos;
|
|
if (init) {
|
|
/* init demo -- display ff resp time meter */
|
|
sprintf(buf, "%dx%d-%d+%d",RF_DEMO_METER_WIDTH, RF_DEMO_METER_HEIGHT, (rf_demoMeterHpos+3) * (RF_DEMO_METER_WIDTH+RF_DEMO_METER_SPACING), vpos * (RF_DEMO_METER_HEIGHT+RF_DEMO_METER_VSPACE));
|
|
sprintf(title,"%s %d/%d Fault-Free Avg User Resp Time (ms)",demoMeterTags[rf_demoMeterTag],C,G);
|
|
ff_avg_resp_time_meter = rf_CreateMeter(title, buf, "blue");
|
|
}
|
|
rc = rf_mutex_init(&iops_mutex);
|
|
if (rc) {
|
|
RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
|
|
__LINE__, rc);
|
|
}
|
|
|
|
meter_update_terminate = 0;
|
|
#ifndef SIMULATE
|
|
pthread_create(&update_thread_desc, raidframe_attr_default, (pthread_startroutine_t)rf_meter_update_thread, NULL);
|
|
#endif /* !SIMULATE */
|
|
gettimeofday(&iops_starttime, NULL);
|
|
recon_initialized = 1;
|
|
}
|
|
|
|
void rf_update_recon_meter(val)
|
|
int val;
|
|
{
|
|
recon_pctg = val;
|
|
}
|
|
|
|
|
|
void rf_finish_recon_demo(etime)
|
|
struct timeval *etime;
|
|
{
|
|
long status;
|
|
int hpos;
|
|
|
|
hpos = rf_demoMeterHpos;
|
|
|
|
recon_initialized = 0; /* make sure any subsequent
|
|
update calls don't do anything */
|
|
recon_pctg = etime->tv_sec; /* display recon time on meter */
|
|
|
|
rf_UpdateMeter(recon_avg_resp_time_meter, (user_ios_recon == 0)? 0: user_resp_time_sum_recon/user_ios_recon);
|
|
|
|
rf_UpdateMeter(recon_pctg_meter, etime->tv_sec);
|
|
|
|
meter_update_terminate = 1;
|
|
|
|
#ifndef SIMULATE
|
|
pthread_join(update_thread_desc, (pthread_addr_t)&status); /* join the meter update thread */
|
|
#endif /* !SIMULATE */
|
|
rf_DestroyMeter(recon_pctg_meter, 0);
|
|
rf_DestroyMeter(ff_avg_resp_time_meter, 0);
|
|
rf_DestroyMeter(deg_avg_resp_time_meter, 0);
|
|
rf_DestroyMeter(recon_avg_resp_time_meter, 0);
|
|
rf_mutex_destroy(&iops_mutex);
|
|
}
|
|
|
|
|
|
/****************************************************************************************
|
|
* meter manipulation code
|
|
***************************************************************************************/
|
|
|
|
#define MAXMETERS 50
|
|
static struct meter_info { int sd; int pid; char name[100]; } minfo[MAXMETERS];
|
|
static int meter_num = 0;
|
|
|
|
int rf_ConfigureMeters()
|
|
{
|
|
int i;
|
|
for (i=0; i<MAXMETERS; i++)
|
|
minfo[i].sd = -1;
|
|
return(0);
|
|
}
|
|
|
|
/* forks a dmeter process to create a 4-digit meter window
|
|
* "title" appears in the title bar of the meter window
|
|
* returns an integer handle (really a socket descriptor) by which
|
|
* the new meter can be accessed.
|
|
*/
|
|
static int rf_CreateMeter(title, geom, color)
|
|
char *title;
|
|
char *geom;
|
|
char *color;
|
|
{
|
|
char geombuf[100], *clr;
|
|
int sd, pid, i, status;
|
|
struct sockaddr sa;
|
|
|
|
if (!geom) sprintf(geombuf,"120x40-0+%d", 50*meter_num); else sprintf(geombuf, "%s", geom);
|
|
clr = (color) ? color : "black";
|
|
sprintf(minfo[meter_num].name,"/tmp/xm_%d",meter_num);
|
|
unlink(minfo[meter_num].name);
|
|
|
|
if ( !(pid = fork()) ) {
|
|
execlp("dmeter","dmeter","-noscroll","-t",title,"-geometry",geombuf,"-sa",minfo[meter_num].name,"-fg",clr,NULL);
|
|
perror("rf_CreateMeter: exec failed");
|
|
return(-1);
|
|
}
|
|
|
|
sd = socket(AF_UNIX,SOCK_STREAM,0);
|
|
sa.sa_family = AF_UNIX;
|
|
strcpy(sa.sa_data, minfo[meter_num].name);
|
|
for (i=0; i<50; i++) { /* this give us 25 seconds to get the meter running */
|
|
if ( (status = connect(sd,&sa,sizeof(sa))) != -1) break;
|
|
#ifdef SIMULATE
|
|
sleep (1);
|
|
#else /* SIMULATE */
|
|
RF_DELAY_THREAD(0, 500);
|
|
#endif /* SIMULATE */
|
|
}
|
|
if (status == -1) {
|
|
perror("Unable to connect to meter");
|
|
exit(1);
|
|
}
|
|
minfo[meter_num].sd = sd;
|
|
minfo[meter_num].pid = pid;
|
|
return(meter_num++);
|
|
}
|
|
|
|
/* causes the meter to display the given value */
|
|
void rf_UpdateMeter(meterid, value)
|
|
int meterid;
|
|
int value;
|
|
{
|
|
if (write(minfo[meterid].sd, &value, sizeof(int)) < sizeof(int)) {
|
|
fprintf(stderr,"Unable to write to meter %d\n",meterid);
|
|
}
|
|
}
|
|
|
|
void rf_DestroyMeter(meterid, killproc)
|
|
int meterid;
|
|
int killproc;
|
|
{
|
|
close(minfo[meterid].sd);
|
|
if (killproc) kill(minfo[meterid].pid, SIGTERM);
|
|
minfo[meterid].sd = -1;
|
|
}
|
|
|
|
int rf_ShutdownAllMeters()
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<MAXMETERS; i++)
|
|
if (minfo[i].sd >= 0)
|
|
rf_DestroyMeter(i, 0);
|
|
return(0);
|
|
}
|
|
|
|
#endif /* RF_DEMO > 0 */
|