Георгий |
Отправлено: 13.04.2004, 21:45 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Оцените, если не сложно, качество кода
до переделки:
sceleton.c
CODE |
#include <time.h>
#include <conio.h>
#include <process.h>
#include <math.h>
#include <sys/kernel.h>
#include <sys/psinfo.h>
#include <sys/osinfo.h>
#include <openDebug.h>
#define GLOBAL
#include "common.h"
#define t_sys_msec 1.e3*(double)(*CurSec)+1.e-6*(double)(*CurNsec)
#define LEN_MAX 160 // ограничение на длину считываемой строки
static SIGTIME last_call;
static unsigned short drv_info_q_idx=0;
pid_t timer_proxy=-1; //t1_a_str (основной опрос)
unsigned char ALG_TYPE;
//--- установка времени перед выходом на Receive() ---
static
void set_q_last_call() {
_disable();
last_call.sec = CUR_SEC;
last_call.nsec = CUR_NSEC;
_enable();
}
//----------------------------------
//--- время (в мсек) между текущим и предыдущим обращением ---
static
long poll_q_start() {
unsigned long msec , sec, nsec;
_disable();
sec = CUR_SEC;
nsec = CUR_NSEC;
_enable();
msec = (sec — last_call.sec)*1000L;
if( nsec < last_call.nsec )
msec = msec + nsec/1000000L — last_call.nsec/1000000L;
else
msec += ( nsec/1000000L — last_call.nsec/1000000L );
last_call.sec = sec;
last_call.nsec = nsec;
return msec;
}
//--- poll_q_start() --------------------------
//-------------------------------------
static
int scan_q_poll() {
int lid, i;
SIG far *sig;
lid = 0;
if( drv_info_q_idx == Channels ) drv_info_q_idx = 0;
for ( i = 0 /*drv_info_q_idx*/; i < Channels; i++ )
{ if( ALG_TYPE &&
(__DrvInfo[i].type == DTT_DO || __DrvInfo[i].type == DTT_AO) ){drv_info_q_idx = i+1; continue;}
sig = &SigTab[ __DrvInfo[i].sid ].sig;
if( __DrvInfo[i].channel <= 0 ) {drv_info_q_idx = i+1; continue;} //сигнал не в конфигурации
if ( (__DrvInfo[i].type == DTT_SG) )
if ( (SigTab[ __DrvInfo[i].sid ].def.channel != 1) && (SigTab[ __DrvInfo[i].sid ].def.channel != 0) ) continue;
if ( !Dinfo->enable_net_out ) break;
if ( __DrvInfo[i].msec >= __DrvInfo[i].poll_msec )
{ drv_info_q_idx = i+1;
drv_info_q[lid++] = i;
}
}
return (lid);
}
//-------------------
//---###sig_handler##-----------------------------------
void sig_handler( int signo )
{ if (open_df_otl == 1) reg_otl=1; else reg_otl=0;
sys_time_str1(str_TIME);
if (signo == SIGUSR2)
{ sprintf(str_otl,"%s Драйвер %s выгружен (остановка ОКО) ",
str_TIME, drv_start_name );
}
else
sprintf(str_otl,"%s Драйвер %s будет выгружен (рестартован) по сигналу %-d ",
str_TIME, drv_start_name, signo );
mprint( 2, str_otl );
//завершить
if (signo == SIGUSR2) { //остановка ОКО
exit(10);
}
SetDiagSig(0,60000.0+(double)signo,0);
if (work_zikl == 1) { //рабочий цикл — рестарт
exit(103);
}
exit(10);
}
//---end sig_handler##-------------------
//------------------------------------------------------
main( int argc, char *argv[] )
{
int kod_task, lid, i, iret;
pid_t pid;
long interval;
SIG far *sig;
struct _osinfo osdata;
int Msg_d_reply_size, Msg_debug_size;
struct Msg_debug Msg_debug;
struct Msg_d_repl Msg_d_reply;
idiag=0; work_zikl=0; reg_otl=0;
drv_info_q_size = 0;
for (i=1; i < 32; i++) { // все системные сигналы кроме SIGINT, SIGQUIT и SIGABRT
if( i == SIGINT || i == SIGQUIT || i == SIGABRT ) continue;
signal( i, sig_handler ); // направить на функцию sig_handler
}
// а этих — игнорировать!
signal( SIGINT, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
signal( SIGABRT, SIG_IGN );
// signal( SIGUSR2, sig_handler );
qnx_osinfo(0, &osdata);
tsize = (double)osdata.tick_size / 1000.0;
Msg_debug_size = sizeof(struct Msg_debug);
Msg_d_reply_size = sizeof(struct Msg_d_repl);
if( argc < 2 ) {
sprintf(str_otl, "(%s): Отсутствует аргумент — стартовое имя драйвера ",
argv[0] );
printf("\r%s\n", str_otl );
SetDiagSig(0, 10000.,0);
return 0;
}
strcpy( drv_start_name, argv[1] );
sprintf(otl_name,"/usr/oko/rtprj/slist/%s.list", drv_start_name);
if( unlink(otl_name) )
{ otladka=0; //отладочного файла нет
df_otl = NULL;
}
else
{ otladka=1; //отладочный файл был
df_otl = fopen( otl_name, "w" ); // откроем его снова
}
sys_time_str1(str_TIME);
sprintf(str_otl, "%s ------------ старт %s", str_TIME, drv_start_name);
mprint(1,str_otl);
//---инициализация драйвера по данным Iniman --
if( !drvInit() ) goto fin;
//--- Армирование к выходным сигналам ----
for( lid = 0; lid < Channels; lid++ )
{ SWInitChannel( lid ); }
//-----------------------------------
//--- Инициализация общая -----------------------------
HWGetConfig(Channels);
sprintf(str_otl,
" Закончен этап инициализации ");
mprint(1, str_otl);
if( i_Config_Poll == 1 ) {
// старт таймера 2 (опрос конфигурации)
timer_start1(&t1_a_str, Config_Poll, 0);
}
if( drv_info_q_size > 0 && !i_Config_Poll )
{ // есть входные сигналы
// старт таймера 1 (опрос входных сигналов)
timer_start1(&t1_a_str, Min_Poll, 0 );
set_q_last_call();
}
work_zikl=1; reg_otl=1;
for (;; ) {
Msg_debug.type=0;
pid = Receive( 0, &Msg_debug, Msg_debug_size );
if( pid == -1 ) continue;
if (Msg_debug.type == debugType) { // вкл/выкл отл.режима
Msg_d_reply.type = debugType;
Reply(pid, &Msg_d_reply, Msg_d_reply_size);
if (Msg_debug.task == '0') { //отключение режима отладки
if (open_df_otl == 1) {
fclose(df_otl);
open_df_otl=0; otladka=0;
}
}
else { //включение режима отладки
kod_task= (int)Msg_debug.task;
if (kod_task < 49) kod_task=1;
if (open_df_otl == 0) {
df_otl=fopen(otl_name, "ab");
if (df_otl != NULL) {
open_df_otl=1;
otladka=kod_task-48;
}
}
}
continue;
}
//---когда сигнал изменился----------------------------
// (обработка выходного сигнала)
if( pid == API_proxy ) {
while( ( lid = dtD_getindex()) != -1 ) {
if (lid >= Channels) continue;
if (__DrvInfo[lid].type != DTT_DO &&
__DrvInfo[lid].type != DTT_AO &&
__DrvInfo[lid].type != DTT_SG ) /*IAV*/ continue;
sig = &SigTab[ __DrvInfo[lid].sid ].sig;
if ( (__DrvInfo[lid].type == DTT_SG) )
if ( (SigTab[ __DrvInfo[lid].sid ].def.channel != 2) && (SigTab[ __DrvInfo[lid].sid ].def.channel != 0) ) continue;
if ( !Dinfo->enable_net_out ) continue;
//--- запись выходного сигнала DO или AO в УСО
iret = HWSetChannel( lid );
if( iret == -1 )
{ timer_start1(&t1_a_str, Config_Poll, 0); //взводим таймер переспроса конф
i_Config_Poll = 1;
break;
}
else i_Config_Poll = 0;
} // end while()
continue;
}
//-----------------------------------
if( pid == timer_proxy )
{ if( i_Config_Poll )//---опрос конфигурации ---
{ if( (iret=HWGetConfig(Channels) ) == -1 )
{ timer_start1(&t1_a_str, Config_Poll, 0); //взводим таймер переспроса конф
i_Config_Poll = 1;
}
else
{ timer_start1(&t1_a_str, Min_Poll, 0 ); //взводим таймер опроса каналов
i_Config_Poll = 0;
set_q_last_call();
}
}
else
{
interval = poll_q_start();
for ( i = 0; i < Channels; i++ )
{ if( ALG_TYPE &&
(__DrvInfo[i].type == DTT_DO || __DrvInfo[i].type == DTT_AO) ) continue;
__DrvInfo[i].msec += interval;
}
lid = scan_q_poll();
if( lid )
{ iret = HWGetChannel( lid, drv_info_q );
//***
if( !iret )
{ timer_start1(&t1_a_str, Config_Poll, 0); //взводим таймер переспроса конф
i_Config_Poll = 1;
continue;
}
}
timer_start1(&t1_a_str, Min_Poll, 0 ); //взводим таймер опроса каналов
i_Config_Poll = 0;
}
continue;
}
}
fin:
sys_time_str1(str_TIME);
sprintf(str_otl,
"%s Драйвер %s выгружен (ошибка при инициализации) ",
str_TIME, drv_start_name);
if (open_df_otl == 1) reg_otl=1; else reg_otl=0;
mprint(2,str_otl);
if( drv_info_q != NULL )
{ for (i=0; i < N_DIAGSIG; i++) SetDiagSig(i, fin_DS_value[i], 0);
}
delay(200);
if( df_otl != NULL ) fclose( df_otl );
if( SIG_pnt != NULL ) free( SIG_pnt );
if( fin_DS_value != NULL ) free( fin_DS_value );
if( __DrvInfo != NULL ) free( __DrvInfo );
if( drv_info_q != NULL ) free( drv_info_q );
return(10);
}
|
common.h
CODE | //--- f_common.h ----
// Описания, включаемые в физическую часть драйвера,
// общие для физической и логической частей драйвера
#ifndef COMMON_H
#define COMMON_H
#include <time.h>
#include <signal.h>
#include <stdio.h> //for FILE
#include <string.h>
#include <sys/proxy.h> //for qnx_proxy_attach
#include <unistd.h> // for access
#include <stdlib.h> // for malloc
#include <iniman.h>
#include <dtd.h>
#ifndef GLOBAL
#define GLOBAL extern
#endif
//------------------------------------------
// Общие константы
//------------------------------------------
#define drv_start_name_DIM 30 //ограничение на размер массива
// (стартовое имя драйвера)
#define str_otl_DIM 160 //ограничение на размер массива
// (строка отладочного вывода)
//-----------------------------------------------
#define CUR_SEC *CurSec
#define CUR_NSEC *CurNsec
//------------------------------------------
// Общие типы
//------------------------------------------
// массив значений параметров драйвера
#ifndef L_COMMON_H
typedef struct {
pid_t proxy;
struct itimerspec timer;
struct sigevent event;
timer_t id;
} TIMER_STR;
//-------------------------------------------
#endif
// T_DRVINFO
typedef struct {
short sid;
long channel;
long msec;
long poll_msec;
char type;
long gsid;
char name[SIGNAME_MAX+1];
int nom_rec;
SIG far *s;
} T_DRVINFO;
//--- включение/выключение режима отлалки ----
#define debugType 0x7776
typedef struct {
int type; // type может быть только debugType
char task; // task = '1', '2', ... '9' — открыть отладочную печать,
// '0' — закрыть
char opts[60]; // до 60 символов под всевозможные дополнительные опции
// печати, на усмотрение пользователя
} T_Msg_debug;
GLOBAL T_Msg_debug Msg_debug;
typedef struct { // ответ по Reply
int type; // type может быть только debugType
} T_Msg_d_reply;
GLOBAL T_Msg_d_reply Msg_d_reply;
GLOBAL int Msg_debug_size, Msg_d_reply_size;
GLOBAL T_DRVINFO *__DrvInfo;
GLOBAL unsigned short Channels;
GLOBAL unsigned long Default_Poll;
//интервал опроса входных сигналов по умолчанию
// (режим работы с входными сигналами — циклический опрос)
GLOBAL unsigned long Min_Poll;
//минимальный интервал опроса входных сигналов
// (режим работы с входными сигналами — циклический опрос)
//------------------------------------
//-----------------------------------------------------------
// Прототипы Общих функций
//-----------------------------------------------------------
int SetDiagSig ( int sig_nom, double value, unsigned short flags );
// — установка диагностического сигнала
void sys_time_str1(char *);
// — занесение в строку системного времени в формате:
// <день>-<месяц>-<год> <час>:<минута>:<секунда>.<миллисекунда>
int mprint( char type, char *str );
SIG far *name_sig( char *name);
// Определение указателя на структуру сигнала по имени
pid_t timer_create1(TIMER_STR *);
// — создание таймера
void timer_start1( TIMER_STR *, long, long);
// — старт таймера
void notify_not_set_time( short int );
int drvInit( void ); //считывание данных из Iniman'a
int SWInitChannel( unsigned short );
int HWSetChannel( unsigned short );
int HWGetConfig(unsigned short);
int HWGetChannel(unsigned short, unsigned short *);
//------------------------------------------
// Общие переменные
//------------------------------------------
GLOBAL double tsize;
GLOBAL char N_DIAGSIG;
GLOBAL pid_t timer_proxy;
GLOBAL char NAME_C[48], ALG_TYPE;
GLOBAL int NUM_NODE;
GLOBAL unsigned short *drv_info_q, drv_info_q_size;
GLOBAL TIMER_STR t1_a_str;
GLOBAL char drv_start_name[drv_start_name_DIM+1]; //стартовое имя драйвера
GLOBAL int otladka; //признак отладочного режима работы
GLOBAL FILE *df_otl;
GLOBAL int open_df_otl;
GLOBAL char otl_name[61];
GLOBAL char str_otl[str_otl_DIM+1]; //строка для вывода в отл.файл
GLOBAL char str_TIME[41];
GLOBAL double *fin_DS_value;
GLOBAL int err_value;
GLOBAL SIGTIME SYS_TIME;
GLOBAL unsigned long Config_Poll;
GLOBAL int idiag, work_zikl, reg_otl, i_Config_Poll //###! опрос конфигурации
;
GLOBAL int Type_Sig_Numb[5];
GLOBAL int DRV_TYPE, PRIO, DS_LOCK_en;
GLOBAL SIG far **SIG_pnt;
//----------------------------
#endif
|
commonFun.c
CODE | #include "common.h"
// Вспомогательные функции логической части драйвера
// timer_create1()
// timer_start1()
// sys_time_str1()
// mprint()
// notify_not_set_time()
// SetDiagSig()
// name_sig()
//----###timer_create1## ----------------
pid_t timer_create1( TIMER_STR *t_a_str )
{
t_a_str->id=-1;
t_a_str->proxy=-1;
// создание proxy-процесса
t_a_str->proxy =
qnx_proxy_attach (0 //подключение proxy-процесса к вызывающему
,NULL,0 //без сообщений
,-1); //с приоритетом вызывающего процесса
if( t_a_str->proxy == -1 ) return (-1);
t_a_str->event.sigev_signo = -(t_a_str->proxy);
t_a_str->id = timer_create( CLOCK_REALTIME, &t_a_str->event );
if( t_a_str->id == -1 ) return (-2);
return (t_a_str->proxy);
}
//---- end timer_create1## -----------------------------
//---###timer_start1## --------------------------------------------
void timer_start1( TIMER_STR *t_a_str, long msec ,long msec_interval)
// msec — через столько миллисекунд таймер пошлет 1-ый сигнал
// вызывающему процессу
// msec_interval — через столько миллисекунд таймер регулярно
// будет посылать сигналы вызывающему процессу
{
t_a_str->timer.it_value.tv_sec = msec / 1000L;
t_a_str->timer.it_value.tv_nsec = (msec % 1000L) * 1000000L;
t_a_str->timer.it_interval.tv_sec = msec_interval / 1000L;
t_a_str->timer.it_interval.tv_nsec = (msec_interval % 1000L) * 1000000L;
timer_settime( t_a_str->id, 0, &t_a_str->timer, NULL );
}
//---end timer_start1##----------------------------
//---###sys_time_str1##----------------------
//--- формирование строки с текущими датой и временем -------
void sys_time_str1
(
char *str // дата-время
)
{
int god, time_msec;
struct tm *tmm;
char *mond[] = { "янв", "фев", "мар", "апр", "май", "июн", "июл",
"авг", "сен", "окт", "ноя", "дек" };
struct timespec time2;
if (work_zikl == 0) //
clock_gettime(CLOCK_REALTIME, &time2);
else { //рабочий цикл
_disable();
time2.tv_sec= CUR_SEC;
time2.tv_nsec= CUR_NSEC;
_enable();
}
SYS_TIME.sec=time2.tv_sec;
SYS_TIME.nsec=time2.tv_nsec;
tmm = localtime(&time2.tv_sec);
time_msec = (int) (time2.tv_nsec / 1000000L);
god = tmm->tm_year + 1900;
sprintf(str,"%2.2i-%s-%4.4i %2.2i:%2.2i:%2.2i.%3.3i ",
tmm->tm_mday, mond[tmm->tm_mon], god,
tmm->tm_hour, tmm->tm_min, tmm->tm_sec, time_msec);
}
//--- end sys_time_str1##--------
//----###mprint##---------------------------
// мультипечать символьной строки.
//-------------------------------------------------------
// Внешние параметры:
// 1) df_otl //файл-дескриптор отладочного файла
//----------------------------------------------------------
// Значение выходного параметра:
// 0 - нормальное завершение
// 1 - ошибка при записи в файл или ошибочный type
//-----------------------------------------------
int mprint(
char type, //0 — только на консоль, 1 — только в файл, 2 — в оба выхода
char *str // строка для вывода
)
{ int cod = 0;
if( type == 0 || type == 2)
{ cod = fprintf( stdout,"\r%s\n", str );
fflush( stdout );
}
if( (type == 1 || type == 2) && df_otl != NULL )
{ cod = fprintf( df_otl, "%s\n", str );
fflush(df_otl);
}
if( cod <= 0 ) return 1;
else return 0;
}
//----end mprint##---------------------
//---###notify_not_set_time##---------------
//--- оповещение об изменении сигнала -------
void notify_not_set_time( short int sid )
{
unsigned short far *notilist;
ICLIST far *iclist;
register int i, flag;
if( sid == -1 ) return;
_disable();
notilist = (unsigned short far*) MK_FP( Dinfo->sid2lid,
sid * ProcCount * 2 );
for( i = 0, flag = 0; i < ProcCount; i++ ) {
if( notilist[i] == 0xFFFF
|| (int)Odsc[i].API_proxy == -1
|| dtD_procid == i ) continue;
if( notilist[i] & 0x8000 ) continue;
notilist[i] |= 0x8000;
iclist = Odsc[i].iclist;
if( iclist->head == iclist->tail ) flag = 1;
iclist->list[ iclist->tail ] = sid;
if( (++iclist->tail) == QueSize ) iclist->tail = 0;
Dinfo->passed++;
if( flag ) {
Trigger( Odsc[i].API_proxy );
flag = 0;
}
}
_enable();
}
//--- end notify_not_set_time## ---------------
//---###SetDiagSig##---------------------------------
// записать в диагностический сигнал драйвера
// аналоговое значение
//--------------------------------------------------------
// Внешние параметры:
// 1) SIG_pnt
// 2) idiag
// 3) DS_LOCK_en
// Возврат 0 — сигнал установлен !0 — не установлен
//-----------------------------------
int SetDiagSig
(
int sig_nom //номер диагностического сигнала (0,1,2,...)
,double value //аналоговое значение
,unsigned short flag //значение флага
)
{ double ddd;
unsigned short oflag;
if (idiag == 0) return 1; //диагностические сигналы не установдены
if (DS_LOCK_en == 1) { //разрешена блокировка сигнала
if (DTS_ISLOCK(SIG_pnt[sig_nom]->flags)) return 2;
}
ddd=SIG_pnt[sig_nom]->value — value;
oflag = SIG_pnt[sig_nom]->flags & 0x00F0;
if (ddd < 0.0) ddd=-ddd;
if (ddd > 0.5 || oflag != flag ) {
SIG_pnt[sig_nom]->value = value;
SIG_pnt[sig_nom]->flags = (SIG_pnt[sig_nom]->flags & 0xFF0F) + flag;
//--- установка времени -------
settime(SIG_pnt[sig_nom], 0);
//-------------------------------
//---- оповещение об изменении сигнала ---
notify_not_set_time ( SIG_pnt[sig_nom]->sid );
//----------------------------------------
return 0;
}
return 1;
}
//----- end SetDiagSig##--------------
//---###settime##---------------------------------
// Установить время сигнала
//--------------------------------------------------------
void settime
(
SIG far *sig
,int settime_var //0-устанавливаемое время определяется по системному
//1-устанавливаемое время определяется по сохраненному
)
{
if (settime_var == 0) {
_disable();
sig->utime.sec = CUR_SEC;
sig->utime.nsec = CUR_NSEC;
_enable();
}
else {
sig->utime.sec = SYS_TIME.sec;
sig->utime.nsec = SYS_TIME.nsec;
}
}
//----- end settime## --------------
//---###name_sig##--------
// Определение указателя на структуру сигнала по имени
// (без армирования)
//------------------------------------
SIG far *name_sig( char *name)
{
short sid;
char far *sname;
for( sid = 0; sid < SidCount; sid++ ) {
sname = &SigTab[ sid ].def.name;
if( sname != NULL ) {
if( _fstricmp( (char far*)name, sname ) == 0 ) {
return (&SigTab[sid].sig);
}
}
}
return (SIGNULL);
}
|
driver.c
CODE | // Функции физической части драйвера QNetExtS
//----------------------------------------------------------------------
//Обслуживание сигналов в сети QNX
//Сигналы опрашиваются циклически с заданным индивидуальным
// интервалом опроса.
//-----------------------------------------------------------------------
// Об остальных внутренних параметрах смотри:
// файлы common.h, f_driver.h
// процедура drvInit.c
//----------------------------------------------------------------------
//---###declare##
#include <sys/types.h>
#include <sys/name.h>
#include <i86.h>
#include <errno.h>
#include <sys/seginfo.h>
#include <conio.h>
#include <sys/inline.h>
#include <sys/kernel.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/dev.h>
#include <fcntl.h>
#include <process.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/vc.h>
#include <openDebug.h>
#include "common.h"
#include "f_driver.h"
//--- переменные физической части ---------
pid_t PID_C;
//--- Структуры запросов и константы обмена с QNetExt
#define GET_INDEX_PER_NAME 1
#define GET_DATUM_PER_INDEX 2
#define SET_DATUM_PER_INDEX 3
#define NUMBER_MAX 50 //### ограничение на длину списка сигналов
//----------------------------------------------
#if __WATCOMC__ > 1000
#pragma pack (__push,1)
#else
#pragma pack (1)
#endif
//#ifdef __cplusplus
//extern "C" {
//#endif
typedef struct {
msg_t type;
char name[32];
} request_t;
typedef struct {
short status;
int index;
char name[32];
}request_reply_t;
typedef struct{
int index;
double data;
short flags;
short level;
struct timespec time;
} oko_signal_t;
typedef struct {
msg_t type;
int number;
int index[NUMBER_MAX];
}get_datum_t;
typedef struct {
short status;
int number;
oko_signal_t oko_signal[NUMBER_MAX];
}get_datum_reply_t;
typedef struct {
msg_t type;
oko_signal_t oko_signal;
}set_datum_t;
typedef struct {
short status;
oko_signal_t oko_signal;
}set_datum_reply_t;
//#ifdef __cplusplus
//};
//#endif
#if __WATCOMC__ > 1000
#pragma pack (__pop)
#else
#pragma pack (0)
#endif
//------------------------------------------
//-----------------------------------------------
union {
msg_t type;
request_t request;
get_datum_t get_datum;
set_datum_t set_datum;
} Send_msg;
request_reply_t request_reply;
get_datum_reply_t get_datum_reply;
set_datum_reply_t set_datum_reply;
//-------------------------------------------------------
// Далее Базисные функции:
//-------------------------------------------------------
//---###SWInitChannel## -------------------------
// 0 — нормальное завершение
int SWInitChannel( unsigned short lid ) //lid номер строки в таблице для сигнала (0,1,...)
{ unsigned char type;
unsigned long gsid;
type = __DrvInfo[lid].type;
gsid = __DrvInfo[lid].gsid;
__DrvInfo[lid].msec = 0;
__DrvInfo[lid].s = NULL;
if( !ALG_TYPE ) return 0;
if ( type == AO_type || type == DO_type || type == SG_type) // IAV
{ __DrvInfo[lid].s = dtD_armsig( gsid, lid, 0, 0 ); }
return(0);
} //---- end SWInitChannel## ------------
//---###HWGetConfig## -------------------------
// Инициализация
//----------------------------------------------------------------------
// Алгоритм:
//
//1. Поиск клиента на заданном узле с заданным именем.
//
//2. Подготовка сети для работы.
//
//3. Регистрация у клиента со всей совокупностью сигналов
// и внесение индексов сигналов в рабочий массив
//
//4. Проверка соответствия сигналов БД и данных ответов клиента.
// Если сигналу БД не соответствует индекс в ответе (сигнала с указанным
// именем у клиента нет, сигнал помечается "не в конфигурации"
// и в дальнейшем (до нового опроса конфигурации) не обрабатывается
// драйвером, кроме того для него драйвер устанавливает в БД признак НОПР
//
//6. Установка значения таймаута на повторный поиск клиента.
int HWGetConfig( unsigned short Channels )
//Channels число сигналов драйвера, заданных в БД
{ int i, lid;
long channels;
unsigned n_cont_real;
pid_t pid;
//------------------------------
//==================================================================
// 1. Поиск клиента на заданном узле с заданным именем.
//==================================================================
if( open_df_otl )
{ sys_time_str1( str_otl );
fprintf( df_otl, "%s HWGetConfig(): Конфигурация: \n", str_otl );
}
i_Config_Poll = 1;
// Определим, запущен ли QNX на узле NUM_NODE
pid = qnx_vc_attach( NUM_NODE, PROC_PID, 0, 0);
if( pid == -1 ) //QNX не запущен на узле NUM_NODE
{ sprintf(str_otl, "на узле %d не запущен QNX",NUM_NODE);
if( !SetDiagSig(0, (double)errno, 0) )
mprint(1, str_otl);
return -1;
}
qnx_vc_detach( pid ); // порушим vcs c Proc32 на узле NUM_NODE
// Определим, запущено ли OKO на узле NUM_NODE (по SoftStart)
pid = qnx_name_locate( NUM_NODE, "SoftStart", 0, &n_cont_real );
if( pid == -1 ) //OKO не запущенo на узле NUM_NODE
{ sprintf(str_otl, "на узле %d не запущенo OKO",NUM_NODE);
if( !SetDiagSig(0, 2.0, 0) )
mprint(1, str_otl);
return -1;
}
qnx_vc_detach( pid ); // порушим vcs c SoftStart на узле NUM_NODE
PID_C = qnx_name_locate( NUM_NODE, NAME_C, 0, &n_cont_real );
if( PID_C == -1 ) // нет такого процесса
{ static char *cmd = "/usr/oko/bin/QNetExt";
char *argv[3], *arge[1];
argv[0] = cmd; argv[1] = NAME_C; argv[2] = NULL; arge[0] = NULL;
//попытаемся запустить процесс на узле NUM_NODE
if( access("/usr/oko/bin/QNetExt", R_OK) == -1 )
{ sprintf(str_otl,"нет процесса /usr/oko/bin/QNetExt");
if( !SetDiagSig(0, 1.0, 0) )
mprint(1, str_otl);
return -1;
}
pid = qnx_spawn( 0, //create a new process
NULL, //let it alloc buffer
NUM_NODE,
-1, // inherit current priority
-1, // inherit current scheduler
_SPAWN_NOZOMBIE, //
cmd, argv, arge, NULL, -1 );
sprintf(str_otl,"Запуск процесса QNetExt на узле %d", NUM_NODE);
if( !SetDiagSig(0, 3.0, 0 ) )
mprint(1, str_otl);
// Запустить таймер для повторного опроса
sleep(7);
return -1;
}
//Есть клиент! Будем регистрироваться!
channels = 0;
for( i = 0; i < Channels; i++ )
{ Send_msg.type = GET_INDEX_PER_NAME;
strcpy( Send_msg.request.name, __DrvInfo[i].name );
lid = Send( PID_C, &Send_msg, &request_reply, sizeof( request_t ), sizeof( request_reply_t ) );
if( lid == -1 ) //нарушение связи
{ i_Config_Poll = 1; // снова на восстановление связи
sprintf(str_otl, "Рухнула связь в процессе регистрации");
if( !SetDiagSig(0, (double)errno, 0) )
mprint(1, str_otl);
return -1;
}
if( request_reply.status == -1 ) __DrvInfo[i].channel = -1;
else { __DrvInfo[i].channel = request_reply.index; channels++; }
}
//-----------------------------------------------
i_Config_Poll = 0;
SetDiagSig(0, .0, DTM_ON);
//==================================================================
// 2. Проверка соответствия сигналов БД и данных конфигурации
//==================================================================
// if( channels != Channels )
{ for( i = 0; i < Channels; i++ )
{ if( __DrvInfo[i].channel == -1 )
{ sprintf(str_otl,
" %s: Сигнал %s не в конфигурации",
drv_start_name, __DrvInfo[i].name );
mprint(2, str_otl);
dtD_notvalid( &SigTab[ __DrvInfo[i].sid ].sig );
}
else
{ sprintf(str_otl,
" Сигнал %s в конфигурации channel %d ",
__DrvInfo[i].name, __DrvInfo[i].channel );
mprint(1, str_otl);
dtD_valid( &SigTab[ __DrvInfo[i].sid ].sig );
__DrvInfo[i].s = &SigTab[ __DrvInfo[i].sid ].sig;
}
}
sprintf(str_otl, "Взаимодействие в норме");
if( !SetDiagSig(0, 1.0*(Channels — channels), DTM_ON) )
mprint(1, str_otl);
}
//------------------------------------------------
sprintf(str_otl," Число рабочих сигналов = %-d ", channels);
mprint(1, str_otl);
return(0);
} //---end HWGetConfig##------------------------
//---###HWSetChannel##--------------------------------------
// запись клиенту по заданному каналу
//----------------------------------------------------------
int HWSetChannel(
unsigned short lid //номер строки в таблице для сигнала (0,1,...)
)
{ int iret;
Send_msg.type = SET_DATUM_PER_INDEX;
if( __DrvInfo[lid].channel > 0 )
{ Send_msg.set_datum.oko_signal.index = __DrvInfo[lid].channel;
if( __DrvInfo[lid].s != NULL /*&& DTS_ISUNLOCK(__DrvInfo[lid].s->flags)*/) // IAV
{ _disable();
Send_msg.set_datum.oko_signal.data = __DrvInfo[lid].s->value;
Send_msg.set_datum.oko_signal.flags = __DrvInfo[lid].s->flags;
Send_msg.set_datum.oko_signal.level = __DrvInfo[lid].s->level;
Send_msg.set_datum.oko_signal.time.tv_sec = __DrvInfo[lid].s->utime.sec;
Send_msg.set_datum.oko_signal.time.tv_nsec = __DrvInfo[lid].s->utime.nsec;
_enable();
}
else return 0;
iret = Send( PID_C, &Send_msg, &request_reply, sizeof( set_datum_t ), sizeof( request_reply_t ) );
if( iret == -1 ) //нарушение связи
{ i_Config_Poll = 1; // снова на восстановление связи
return -1;
}
if( request_reply.status == -1 ) __DrvInfo[lid].channel = -1;
else { __DrvInfo[lid].channel = request_reply.index; }
}
return 0;
} //----- end HWSetChannel## -------------------
//---###HWGetChannel## -------------------------
// Запрос у клиента информации
//-----------------------------------------------
int HWGetChannel(
unsigned short lid //Количество сигналов в списке для опроса drv_info_q
, unsigned short *drv_info_q //списoк для опроса
)
{ int i, j, iret, sent = 0, ic;
long sec, nsec;
double dt;
if( i_Config_Poll ) return 0; // а связь-то порушена
Send_msg.type = GET_DATUM_PER_INDEX;
Send_msg.get_datum.number = 0;
if( open_df_otl )
{ sys_time_str1( str_otl );
fprintf( df_otl, "%s Запрос по %d сигналам:", str_otl, lid );
}
for( ic = 0; ic < lid; ic++ ) //Цикл по списку опроса
{ i = drv_info_q[ic];
if( __DrvInfo[i].channel <= 0 || __DrvInfo[i].s == NULL
/*|| DTS_ISLOCK(__DrvInfo[i].s->flags)*/ ) continue;
if( open_df_otl )
{ fprintf( df_otl, " %d,", __DrvInfo[i].channel );
}
Send_msg.get_datum.index[Send_msg.get_datum.number++] = __DrvInfo[i].channel;
__DrvInfo[i].msec = 0;
if( Send_msg.get_datum.number == NUMBER_MAX )
{ sent = 1;
sec = *CurSec; nsec = *CurNsec;
iret = Send( PID_C, &Send_msg, &get_datum_reply, sizeof( get_datum_t ), sizeof( get_datum_reply_t ) );
if( iret == -1 ) //нарушение связи
{ i_Config_Poll = 1; // снова на восстановление связи
return 0;
}
if( get_datum_reply.status == -1 )
{ i_Config_Poll = 1; // снова на восстановление связи
return 0;
}
if( open_df_otl )
{ dt = ( (double)(*CurSec — sec) + (double)(*CurNsec — nsec) * 1E-9 ) * 1000;
fprintf(df_otl,"\n Ответ по %d сигналам %6.2f\n",get_datum_reply.number,dt);
}
for( j = 0; j < get_datum_reply.number; j++ )
{ set_signal( &get_datum_reply.oko_signal[j] ); }
Send_msg.get_datum.number = 0;
}
}
if( Send_msg.get_datum.number )
{ sent = 1;
sec = *CurSec; nsec = *CurNsec;
iret = Send( PID_C, &Send_msg, &get_datum_reply, sizeof( get_datum_t ), sizeof( get_datum_reply_t ) );
if( iret == -1 ) //нарушение связи
{ i_Config_Poll = 1; // снова на восстановление связи
return 0;
}
if( get_datum_reply.status == -1 )
{ i_Config_Poll = 1; // снова на восстановление связи
return 0;
}
Send_msg.get_datum.number = 0;
if( open_df_otl )
{ dt = ( (double)((long)*CurSec — sec) + (double)((long)*CurNsec — nsec) * 1E-9 ) * 1000;
fprintf(df_otl,"\n Ответ по %d сигналам %6.3f\n",get_datum_reply.number,dt);
}
for( j = 0; j < get_datum_reply.number; j++ )
{ set_signal( &get_datum_reply.oko_signal[j] ); }
}
/* if( !sent )
{ //qnx_vc_detach( PID_C );
//i_Config_Poll = 1; // снова на восстановление связи
return 0;
}*/
return 1;
} //---- end HWGetChannel## ------------
void set_signal( oko_signal_t *oko_s )
{ int i, update = 0;
for( i = 0; i < Channels; i++ )
{ if( __DrvInfo[i].channel == oko_s->index ) break; }
if( i >= Channels ) return;
if( __DrvInfo[i].s == NULL )
{ printf("Плохо инициировал массив channel %d\n", oko_s->index ); return;}
if( __DrvInfo[i].s->value != oko_s->data )
{ __DrvInfo[i].s->value = oko_s->data; update = 1; }
if( __DrvInfo[i].s->flags != oko_s->flags )
{ __DrvInfo[i].s->flags = oko_s->flags; update = 1; }
if( __DrvInfo[i].s->level != oko_s->level )
{ __DrvInfo[i].s->level = oko_s->level; update = 1; }
if( update )
{ __DrvInfo[i].s->utime.sec = oko_s->time.tv_sec;
__DrvInfo[i].s->utime.nsec = oko_s->time.tv_nsec;
notify_not_set_time(__DrvInfo[i].sid);
}
}
|
после реконструирования:
Drv_QNetExt.hpp
CODE | #ifndef DRV_QNET_EXT_HPP_INCLUDED
#define DRV_QNET_EXT_HPP_INCLUDED
#include <wcdefs.h>
#include <time.h>
extern "C"{
#include <dtd.h>
};
#include <QNetExt.h>
#include "Timer.hpp"
class DrvQNetExt
{
protected:
unsigned long lSetSignalMask;
//константы указывающие, как трактовать значение поля channel сигнала
enum SendMode{ OnlySend=2, //эти только посылать
OnlyReq=1, //эти только запрашивать
SendReq=3, //и посылать и запрашивать
None=0 //не посылать и не запрашивать
};
//структура описывающая связь локального сигнала и удаленного
struct structSigInfo
{
long remote_gsid;//gsid на удаленном узле
SIG far *ptrSignal; //прямой указатель на структуру SIG
int msec; //время с последней передачи
int poll; //период опроса ( в ms )
int channel; // #канала этого сигнала
};
//массив связей сигналов
struct structSigInfoArray
{
structSigInfo *ptrData;
structSigInfo **FastSearchIndex; //массив указателей упорядоченный по remote_gsid
unsigned short Length;
} SigInfo;
//массив индексов для периодического опроса
struct structReqQueryArray
{
unsigned short *ptrIndex; //массив индексов
unsigned short Filled; //число заполненных элементов
} ReqQuery;
SIG far *ptrDiag;//указатель на диагностический сигнал
//параметры опроса
struct structPoll
{
int Config; //период переспроса конфигурации (в ms)
int Data; //период переопроса сигналов (в ms)
} Poll;
struct structServer
{
char Name[48]; //имя пассивной части
nid_t Node; //номер узла, где искать пассивную часть
pid_t Vid; //pid виртуального канала связи с сервером
} Server;
Timer WorkTimer; //таймер опроса конфигурации или данных
struct structRealTime
{
time_t far * sec; //текущее время
time_t far * nsec; // ( указатель на системную ячейку времени )
} RealTime;
timespec LastCallTime; //время последней выборки сигналов для передачи
//выполняет полную инициализацию объекта статической информацией
// возврат - TRUE, если собрал достаточно информации для дальнейшей работы
// FALSE — при критических ошибках сбора
WCbool LoadConfig ( const char *StartName );
//вывод на печать информации о сигналах
void PrintSigInfo ( const structSigInfo *ptrSigInfo, unsigned short len )const;
//вывод на печать конфигурации объекта
void PrintConfig ( void )const;
//выполняет поиск сервера на заданном узле с заданным именем
// возврат — vid сервера
pid_t FindServer ( int NodeN,
const char* RemoteName
)const;
//выполняет построение таблицы связей сигналов локального узла и удаленного
// в структуре должны быть заполнено поле ptrSignal
// возврат — TRUE - при корректном обмене с сервером и нормальном постоении таблицы
// FALSE - при критических ошибках
// устанавливает в НОПР те сигналы, которые не обнаружены у сервера
// все обнаруженные в ОПР
WCbool RegisterServer ( pid_t pid,
structSigInfo *ptrSigInfo,
unsigned short len,
WCbool PrintStatus=FALSE //печать при обнаружении не критических ошибок
)const;
//ищет клиента и подключается к нему
// возврат TRUE если все успешно, FALSE при наличии ошибок
//
// использует поля SigInfoLength, ptrSigInfo, ServerNode, ServerName
//
WCbool Connect ( void );
// посылает запрос серверу на запись
// в случае ошибок разрывает связь, возвращает FALSE, перепрограммирует таймер
WCbool SendWriteReq ( unsigned short SignalIndex//lid сигнала
);
//
// посылает запросы на сервер для считывания сигналов согласно списку опроса
// использует поля ReqQueryFilledSize, ptrSigReqQuery, ptrSigInfo, SigInfoLength, ServerVid
//
WCbool SendReadReq ( void );
void SetSignal( const oko_signal_t *oko_s );
//
// выполняет построение запроса
// возврат — число элементов в запросе
//
int BuildDataReq ( get_datum_t *Req,
unsigned short MaxSig,
const unsigned short *drv_info_q,
unsigned short listSize,
const structSigInfo *ptrSigInfo);
unsigned short BuildReqList( void );
//если находит в файле конфигурации диагностический сигнал,
//то указатель на него записывает в ptrDiagSig и возврат TRUE
//если не находит, то возврат FALSE
WCbool ConnectToDiagSig ( const char* drv_start_name,
int sec //#секции этого драйвера
);
void UpLink (void);//вызывается при возобновлении связи
void DownLink (void);//вызывается при потере связи
void TimeStep (void);//увеличивает значение в поле сигнала msec
long CallInterval (void);//возвращает время между своими вызовами
void PrepareFastSearch(void);//выполняет сортировку по remote_gsid
//для более быстрого поиска при получении ответа от сервера
WCbool LoadConfig (const char *StartName);
enum QNetExtDiagState { noQNX, //узел недоступен
noOKO, //не найдено OKO
noQNetExt, //нет пассивной части
errorConfig, //ошибка конфигурации
linkOk, //связь в порядке
noLink, //драйвер еще не вошел в рабочий цикл
linkFauled //в процессе обмена с сервером связь была прервана
};
void SetDiagSig ( QNetExtDiagState state)const;
WCbool NeedRun;
public:
DrvQNetExt(void);
~DrvQNetExt(void);
WCbool Prepare ( const char *StartName );
void Execute(void);
//методы для вызова из обработчика сигналов
//подготавливает объект к выгрузке
void Shutdown(void);
//переводит объект в состояние спячки
// никакие запросы на сервер не посылаются
void Suspend(void);
//пробуждает объект
// продолжается работа с сервером
void Resume(void);
};
#endif
|
Отредактировано Георгий — 13/04/2004, 22:51 |
|
Георгий |
Отправлено: 13.04.2004, 21:47 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
всё в одно сообщение, к сожалению, не поместилось
Drv_QNetExt.cpp
CODE | #define NDEBUG
#define NO_SPEED_BENCH
#ifndef NO_SPEED_BENCH
#include <iostream.h>
#include <fstream.h>
#include "UtilsSGV/Bench.hpp"
Bench bench;
#endif
#include "Drv_QNetExt.hpp"
#include <sys/osinfo.h>
#include <sys/vc.h>
#include <sys/name.h>
extern "C"{
#include <iniman.h>
#include <dtd.h>
};
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stddef.h>
#include <assert.h>
#include <errno.h>
void notify_not_set_time( short int sid );
int FastSearchRemoteGsidCompareFunction( const void *p1, const void *p2 )
{
const DrvQNetExt::structSigInfo &Sig_1 = **(DrvQNetExt::structSigInfo**) p1;
const DrvQNetExt::structSigInfo &Sig_2 = **(DrvQNetExt::structSigInfo**) p2;
return Sig_1.remote_gsid-Sig_2.remote_gsid;
};
DrvQNetExt::DrvQNetExt(void)
{
this->SigInfo.ptrData = 0;
this->SigInfo.Length = 0;
this->ReqQuery.ptrIndex = 0;
this->ReqQuery.Filled = 0;
this->ptrDiag = SIGNULL;
this->Poll.Config = -1;
this->Poll.Data = -1;
this->Server.Node = -1;
this->Server.Vid = -1;
this->RealTime.sec = SIGNULL;
this->RealTime.nsec = SIGNULL;
this->LastCallTime.tv_sec = 0;
this->LastCallTime.tv_nsec = 0;
};
DrvQNetExt::~DrvQNetExt(void)
{
delete this->SigInfo.ptrData;
delete this->ReqQuery.ptrIndex;
};
WCbool DrvQNetExt::Prepare ( const char *StartName )
{
if ( !this->LoadConfig( StartName ) )
{
this->SetDiagSig( errorConfig );
return FALSE;
}
else{
this->SetDiagSig( noLink );
#ifndef NO_SPEED_BENCH
bench.Prepare(20);
#endif
return TRUE;
};
};
//выполняет поиск сервера на заданном узле с заданным именем
// возврат — vid сервера
pid_t DrvQNetExt::FindServer ( int NodeN, const char* ServerName )const
{
const char *SoftStartName="SoftStart";
const char *RemoteName=ServerName;
pid_t LocalPid;
// Определим, запущен ли QNX на узле NUM_NODE
LocalPid = qnx_vc_attach( NodeN,PROC_PID, 0, 0);
if( LocalPid == -1 ) //QNX не запущен на узле NUM_NODE
{
#ifdef SEND_ARS_MESSAGES
ars_msg( msg_file, msg_noqnx, msg_alarm, empty_msg );
#endif
this->SetDiagSig( noQNX );
return -1;
};
qnx_vc_detach( LocalPid ); // порушим vcs c Proc32 на узле NUM_NODE
// Определим, запущено ли OKO на узле NUM_NODE (по SoftStart)
LocalPid = qnx_name_locate( NodeN, SoftStartName, 0, 0 );
if( LocalPid == -1 ) //OKO не запущенo на узле NUM_NODE
{
#ifdef SEND_ARS_MESSAGES
ars_msg( msg_file, msg_nooko, msg_alarm, empty_msg );
#endif
this->SetDiagSig( noOKO );
return -1;
}
qnx_vc_detach( LocalPid ); // порушим vcs c SoftStart на узле NUM_NODE
LocalPid = qnx_name_locate( NodeN, RemoteName, 0, 0 );
if( LocalPid == -1 ) // нет такого процесса
{
#ifdef SEND_ARS_MESSAGES
ars_msg( msg_file, msg_nokl, msg_warning, empty_msg );
#endif
this->SetDiagSig( noQNetExt );
return -1;
}//не найден клиент
return LocalPid;
};
//выполняет построение таблицы связей сигналов локального узла и удаленного
// в структуре должны быть заполнено поле ptrSignal
// возврат — TRUE - при корректном обмене с сервером и нормальном постоении таблицы
// FALSE - при критических ошибках
// устанавливает в НОПР те сигналы, которые не обнаружены у сервера
// все обнаруженные в ОПР
WCbool DrvQNetExt::RegisterServer ( pid_t pid,
structSigInfo *ptrSigInfo,
unsigned short len,
WCbool PrintStatus //печать при обнаружении не критических ошибок
)const
{
request_t Req;
request_reply_t Rep;
int i, ret;
Req.type = GET_GSID_PER_NAME;
for( i = 0; i < len; i++ )
{//перебор всех сигналов узла
_fstrncpy( Req.name, SigTab[ptrSigInfo[i].ptrSignal->sid].def.name, sizeof(Req.name) );
ret = Send( pid, &Req, &Rep, sizeof( Req ), sizeof( Rep ) );
if( ret == -1 ) //нарушение связи
{
#ifdef SEND_ARS_MESSAGES
ars_msg( msg_file, link_err, msg_warning, empty_msg );
#endif
this->SetDiagSig( linkFauled );
return FALSE;
}
if( Rep.status == -1 )
{
if ( PrintStatus )
printf(" DrvQNetExt : сигнал не найден gsid=%i\n", SigTab[ptrSigInfo[i].ptrSignal->sid].def.gsid);
dtD_notvalid( ptrSigInfo[i].ptrSignal );
ptrSigInfo[i].remote_gsid = -1;
}
else
{
dtD_valid( ptrSigInfo[i].ptrSignal );
ptrSigInfo[i].remote_gsid = Rep.gsid;
};
}//цикл перебора по каналам
return TRUE;
};
//ищет клиента и подключается к нему
// возврат TRUE если все успешно, FALSE при наличии ошибок
//
// использует поля SigInfoLength, ptrSigInfo, ServerNode, ServerName
//
WCbool DrvQNetExt::Connect ( void )
{
pid_t pid;
const pid_t InvalidPid=-1;
const char *RemoteName=this->Server.Name;
pid=FindServer( this->Server.Node, RemoteName );
if ( pid == -1 )
return FALSE;
//Есть клиент! Будем регистрироваться!
if ( !RegisterServer( pid , this->SigInfo.ptrData, this->SigInfo.Length ) )
{
this->Server.Vid=InvalidPid;
return FALSE;
}
else{
this->Server.Vid=pid;
return TRUE;
};
};
// посылает запрос серверу на запись
// в случае ошибок разрывает связь, возвращает FALSE, перепрограммирует таймер
WCbool DrvQNetExt::SendWriteReq
( unsigned short SignalIndex )
{
int iret;
set_datum_t Req;
set_datum_reply_t Rep;
assert( this->Server.Vid != -1 );
assert( SignalIndex<this->SigInfo.Length );
const SIG far *ptrSig=this->SigInfo.ptrData[SignalIndex].ptrSignal;
const long remote_gsid=this->SigInfo.ptrData[SignalIndex].remote_gsid;
assert( ptrSig != SIGNULL );
assert( remote_gsid != -1 );
Req.type = SET_DATUM_PER_GSID;
Req.sig.gsid = remote_gsid;
_disable();
Req.sig.value = ptrSig->value;
Req.sig.flags = ptrSig->flags;
Req.sig.level = ptrSig->level;
Req.sig.utime.sec = ptrSig->utime.sec;
Req.sig.utime.nsec = ptrSig->utime.nsec;
_enable();
iret = Send( this->Server.Vid, &Req, &Rep, sizeof( Req ), sizeof( Rep ) );
if( iret == -1 ) //нарушение связи
{
return FALSE;
};
if( Rep.status == -1 )
{//удаленная сторона сигнализирована об ошибке — возможно net_out != 1
//продолжаем как ни вчем ни бывало
return TRUE;
};
return TRUE;
};
//
// посылает запросы на сервер для считывания сигналов согласно списку опроса
// использует поля ReqQueryFilledSize, ptrSigReqQuery, ptrSigInfo, SigInfoLength, ServerVid
//
WCbool DrvQNetExt::SendReadReq ( void )
{
int j, iret;
unsigned short i;
get_datum_t Req;
get_datum_reply_t Rep;
Rep.status=-1;
assert( this->Server.Vid != -1 );
Req.type = GET_DATUM_PER_GSID;
const unsigned short nSig=this->ReqQuery.Filled;
assert( nSig <= this->SigInfo.Length );
//формируем запрос на получение данных
for( i = 0; i < nSig; ) //Цикл по списку опроса
{
//выборка не более NUMBER_MAX сигналов и формирование запроса
const unsigned short sigN=(unsigned short)(nSig-i);
#ifndef NO_SPEED_BENCH
bench.Enter(0);
#endif
i+=BuildDataReq( &Req,
NUMBER_MAX,
&this->ReqQuery.ptrIndex[i],
sigN,
this->SigInfo.ptrData );
#ifndef NO_SPEED_BENCH
bench.Leave(0);
#endif
#ifndef NO_SPEED_BENCH
bench.Enter(1);
#endif
//посылка запроса
iret = Send( this->Server.Vid, &Req, &Rep, sizeof( Req ), sizeof( Rep ) );
#ifndef NO_SPEED_BENCH
bench.Leave(1);
#endif
if( iret == -1 ) //нарушение связи
{
return FALSE;
};
if( Rep.status == -1 )
return TRUE;//пассивная часть чемто занята — продолжать нет смысла
#ifndef NO_SPEED_BENCH
bench.Enter(2);
#endif
for( j = 0; j < Rep.number; j++ )
{
#ifndef NO_SPEED_BENCH
bench.Enter(3);
#endif
SetSignal( &Rep.sig[j] );
#ifndef NO_SPEED_BENCH
bench.Leave(3);
#endif
};
#ifndef NO_SPEED_BENCH
bench.Leave(2);
#endif
};//конец цикла по списку опроса
return TRUE;
};
void DrvQNetExt::SetSignal( const oko_signal_t *oko_s )
{
unsigned short i;
WCbool update=FALSE;
const unsigned short mask = 0xEFFF;
const structSigInfo *ptrDrvInfo=this->SigInfo.ptrData;
//подготовка к быстрому поиску
structSigInfo KeySig;
KeySig.remote_gsid=oko_s->gsid;
structSigInfo *pKey=&KeySig;
void *SearchResult;
SearchResult=bsearch( &pKey,
this->SigInfo.FastSearchIndex,
this->SigInfo.Length,
sizeof( this->SigInfo.FastSearchIndex[0] ),
FastSearchRemoteGsidCompareFunction );
if( !SearchResult )
{
printf(" странный ответ от удаленной стороны. remote_gsid=%i не найден среди запрошенных сигналов\n",oko_s->gsid);
return;
};
structSigInfo *pSigInfo= *(structSigInfo**)SearchResult;
SIG far * sig=pSigInfo->ptrSignal;
if( sig == SIGNULL )
{
printf("Плохо инициировал массив channel remote_gsid=%i index=%i\n", oko_s->gsid, i );
return;
};
_disable();
if ( this->lSetSignalMask & 0x01 )
if( sig->value != oko_s->value )
{
sig->value = oko_s->value;
update = TRUE;
}
if ( this->lSetSignalMask & 0x02 )
if( sig->flags != oko_s->flags )
{
sig->flags = oko_s->flags;
update = TRUE;
}
const unsigned short MaskedMyLevel = sig->level & mask;
const unsigned short MaskedRemoteLevel = oko_s->level & mask;
if ( this->lSetSignalMask & 0x04 )
if( MaskedMyLevel != MaskedRemoteLevel )
{
sig->level = oko_s->level;
update = TRUE;
}
if( update )
{
if ( this->lSetSignalMask & 0x08 )
{
sig->utime.sec = oko_s->utime.sec;
sig->utime.nsec = oko_s->utime.nsec;
}
else{
sig->utime.sec = *this->RealTime.sec;
sig->utime.nsec = *this->RealTime.nsec;
};
notify_not_set_time(sig->sid);
}
_enable();
}
//
// выполняет построение запроса
// возврат — число элементов в запросе
//
int DrvQNetExt::BuildDataReq ( get_datum_t *Req,
unsigned short MaxSig,
const unsigned short *drv_info_q,
unsigned short listSize,
const structSigInfo *ptrSigInfo)
{
int i;
unsigned short filledSize;
for( i = 0, filledSize=0; (i < listSize) && (filledSize < MaxSig); i++ )
{
const structSigInfo *ptrWorkElem = &ptrSigInfo[ drv_info_q[i] ];//рабочий элемент
assert( ptrWorkElem );
if ( ptrWorkElem->remote_gsid == -1 ) continue;
assert( ptrWorkElem->ptrSignal != SIGNULL );
Req->gsid[filledSize++] = ptrWorkElem->remote_gsid;
};
Req->number=filledSize;
return filledSize;
};
unsigned short DrvQNetExt::BuildReqList( void )
{
unsigned short i,filled;
const unsigned short len = this->SigInfo.Length;
for ( filled=0,i = 0; i < len; i++ )
{
const int channel = this->SigInfo.ptrData[i].channel;
const SIG far *sig = this->SigInfo.ptrData[i].ptrSignal;
if ( (channel != OnlyReq) && (channel != SendReq) ) continue;
if ( this->SigInfo.ptrData[i].msec >= this->SigInfo.ptrData[i].poll )
{
this->ReqQuery.ptrIndex[filled++] = i;
this->SigInfo.ptrData[i].msec = 0;//сигнал поставлен в очередь (можно считать, что он уже передался)
};
};
this->ReqQuery.Filled=filled;
return filled;
};
void notify_not_set_time( short int sid )
{
unsigned short far *notilist;
ICLIST far *iclist;
register int i, flag;
if( sid == -1 ) return;
// _disable();
notilist = (unsigned short far*) MK_FP( Dinfo->sid2lid,
sid * ProcCount * 2 );
for( i = 0, flag = 0; i < ProcCount; i++ ) {
if( notilist[i] == 0xFFFF
|| (int)Odsc[i].API_proxy == -1
|| dtD_procid == i ) continue;
if( notilist[i] & 0x8000 ) continue;
notilist[i] |= 0x8000;
iclist = Odsc[i].iclist;
if( iclist->head == iclist->tail ) flag = 1;
iclist->list[ iclist->tail ] = sid;
if( (++iclist->tail) == QueSize ) iclist->tail = 0;
Dinfo->passed++;
if( flag ) {
Trigger( Odsc[i].API_proxy );
flag = 0;
}
}
// _enable();
}
//--- end notify_not_set_time## ---------------
void DrvQNetExt::UpLink (void)//вызывается при возобновлении связи
{
#ifndef NO_SPEED_BENCH
bench.Enter(4);
#endif
const unsigned int sec = this->Poll.Data/1000;
const unsigned int nsec = (this->Poll.Data%1000)*1000000;
//подготовка к быстроку поиску
this->PrepareFastSearch();
this->WorkTimer.SetInterval( sec, nsec );
this->SetDiagSig( linkOk );
#ifndef NO_SPEED_BENCH
bench.Leave(4);
#endif
};
void DrvQNetExt::DownLink(void)//вызывается при потере связи
{
#ifndef NO_SPEED_BENCH
bench.Enter(5);
#endif
qnx_vc_detach( this->Server.Vid );
this->Server.Vid = -1;
const unsigned int sec = this->Poll.Config/1000;
const unsigned int nsec = (this->Poll.Config%1000)*1000000;
this->WorkTimer.SetInterval( sec, nsec );
for(unsigned short i=0;i< this->SigInfo.Length; i++)
{
structSigInfo &sig=this->SigInfo.ptrData[i];
sig.remote_gsid=-1;
if ( sig.ptrSignal )
dtD_notvalid( sig.ptrSignal );
};
this->SetDiagSig( linkFauled );
#ifndef NO_SPEED_BENCH
bench.Leave(5);
#endif
};
void DrvQNetExt::TimeStep( void )
{
unsigned short i;
const unsigned short len = this->SigInfo.Length;
const int increment = this->CallInterval();
for (i=0;i<len;i++) this->SigInfo.ptrData[i].msec+=increment;
};
long DrvQNetExt::CallInterval( void )
{
_disable();
const int sec = *this->RealTime.sec;
const int nsec = *this->RealTime.nsec;
_enable();
int diffSec = sec — this->LastCallTime.tv_sec;
int diffNSec = nsec — this->LastCallTime.tv_nsec;
if ( diffNSec < 0 )
{
diffSec--;
diffNSec+=1000000000;
}
const int increment= ( diffSec > (INT_MAX/1000) )? INT_MAX : (diffSec*1000)+(diffNSec/1000000);
this->LastCallTime.tv_sec = sec;
this->LastCallTime.tv_nsec = nsec;
return increment;
};//
void DrvQNetExt::Execute(void)
{
this->CallInterval();
this->DownLink();
const pid_t timer_proxy=this->WorkTimer.GetProxy();
prog_ready();//прогроамма готова — для критического старта
this->NeedRun = TRUE;
this->SetDiagSig( noLink );
for (; this->NeedRun; )
{
const pid_t pid = Receive( 0, 0, 0 );//мы получаем только proxy сообщения от Dam и таймера
if( pid == -1 ) continue;
//---когда сигнал изменился----------------------------
// (обработка выходного сигнала)
if( pid == API_proxy )
{
unsigned short lid;
const unsigned short InvalidLid=-1;
while( ( lid = dtD_getindex()) != InvalidLid )
{
if ( this->Server.Vid == -1 ) continue;//связи нет и передавать ничего не будем!
if ( !Dinfo->enable_net_out ) continue;
if (lid >= this->SigInfo.Length ) continue;
#ifndef NO_SPEED_BENCH
bench.Enter(6);
#endif
const structSigInfo &drvInfo = this->SigInfo.ptrData[lid];
const sid = drvInfo.ptrSignal->sid;
const channel = drvInfo.channel;
assert( !(( channel != OnlySend ) && ( channel != SendReq )) );
const WCbool ret = this->SendWriteReq( lid );
#ifndef NO_SPEED_BENCH
bench.Leave(6);
#endif
if( ret == FALSE )
{
this->DownLink( );
break;
}
} // end while()
#ifndef NO_SPEED_BENCH
fstream fs("/bench_out.txt",ios::out|ios::append);
int i;
for(i=0;i<bench.GetResults().length();++i)
{
fs<<bench.GetPointInfo(i)<<endl;
};
fs<<bench.GetCPUClock()<<endl;
#endif
continue;
};//if( pid == API_proxy )
// ---------- обработка таймера ----------------
if( pid == timer_proxy )
{
while ( (Creceive(timer_proxy, 0, 0) != -1) || (errno!=ENOMSG) );
if( this->Server.Vid == -1 )// опрос конфигурации и установка связи
{
#ifndef NO_SPEED_BENCH
bench.Enter(8);
#endif
const WCbool con=this->Connect();//пробуем опросить сервер
#ifndef NO_SPEED_BENCH
bench.Leave(8);
#endif
if( con )
{
//связь установилась — включаем опросы каналов
UpLink( );
};
}
else
{//таймер опроса каналов
if ( !Dinfo->enable_net_out ) continue;
#ifndef NO_SPEED_BENCH
bench.Enter(7);
#endif
//увеличиваем счечик времени
this->TimeStep( );
//построение списка индексов посылаемых сигналов
const unsigned short ReqSigN= BuildReqList( );
if( ReqSigN )
{
const WCbool ret = SendReadReq();
if( !ret )
{
DownLink( );
continue;
}
}
#ifndef NO_SPEED_BENCH
bench.Leave(7);
#endif
}//сообщение от таймера опроса каналов
continue;
}//прием сообщений от таймера
}//вечный цикл приема сообщений
};//DrvQNetExt::Execute
void DrvQNetExt::PrepareFastSearch(void)
{
//выполняем сортировку массива индексов
qsort( this->SigInfo.FastSearchIndex,
this->SigInfo.Length,
sizeof( this->SigInfo.FastSearchIndex[0] ),
FastSearchRemoteGsidCompareFunction );
};
//методы для вызова из обработчика сигналов
//подготавливает объект к выгрузке
void DrvQNetExt::Shutdown(void)
{
};
//переводит объект в состояние спячки
// никакие запросы на сервер не посылаются
void DrvQNetExt::Suspend(void)
{
};
//пробуждает объект
// продолжается работа с сервером
void DrvQNetExt::Resume(void)
{
};
void DrvQNetExt::SetDiagSig ( QNetExtDiagState estate)const
{
if ( !this->ptrDiag ) return;
double local_value=0;
WCbool state=FALSE;
switch ( estate )
{
case noQNX:
local_value=1;
break;
case noOKO:
local_value=2;
break;
case noQNetExt:
local_value=3;
break;
case errorConfig:
local_value=4;
break;
case noLink:
local_value=5;
break;
case linkOk:
state=TRUE;
break;
case linkFauled:
local_value=6;
break;
default:
local_value=666;
}//switch state
if ( ptrDiag->value!=local_value )
{
ptrDiag->value=local_value;
if ( state ) DTS_ON( ptrDiag->flags );
else DTS_OFF( ptrDiag->flags );
dtD_notify( ptrDiag->sid );
};
};
| |
|
Deem |
Отправлено: 23.04.2004, 16:36 |
|
Мастер участка
Группа: Участник
Сообщений: 327
|
Все целиком как-то в голову не лезет. Чтоб оценить качество, надо нескольким человекам решить общую задачу по-своему, а потом выбрать оптимальный вариант. А с ним уже сравнивать тестируемый
Мне не нравиться отсутствие видимых уровней вложенности, читать трудновато. Если работает, думаю — нормально. А ваще, чужой код оцениывать — хуже некуда.
Отредактировано Deem — 23/04/2004, 17:42
|
|
Георгий |
Отправлено: 23.04.2004, 23:24 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Видимые уровни вложенности были, но после поста все повторяющиеся пробелы в начале строк превратились в один единственный...
читать в таком виде действительно херово...
вариант "до переделки" не мой и не во всех ситуациях работающий корректно.
"после переделки" — мой. переделывал на спор и уложился в 4 рабочих дня. мой вариант работает в 3 раза быстрее не переделанного и во всех тех ситуациях, когда его предок давал сбой, мой держится молодцом
( сам себя не похвалишь — никто не похвалит )
PS. про качество я сам сделал вывод — хреновое, раз за 10 дней никто так и не смог разобраться в программе и высказать своё мнение. |
|
Иван |
Отправлено: 24.04.2004, 00:16 |
|
Машинист паровоза
Группа: Участник
Сообщений: 207
|
Георгий, извините конечно что вопрос не по теме, но все же,
у вас хватает времени на работе заниматься посторонними делами,или это просто определение "рабочий день"?
|
|
Георгий |
Отправлено: 24.04.2004, 09:31 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Хм.. Я системный программист — и программы, подобный приведённой, моё основной занятие. Срочная переделка понадобилась для успешной демонстрации заказщику всеко комплекса ПО, частью которого и является приведённый код.
PS. так что это не "посторонние дела" , а нормальный рабочий процесс
Отредактировано Георгий — 24/04/2004, 10:35 |
|
Иван |
Отправлено: 25.04.2004, 21:26 |
|
Машинист паровоза
Группа: Участник
Сообщений: 207
|
Извините за, может быть, неточную формулировку,
но я имел ввиду вот что:QUOTE | переделывал на спор |
|
|
Георгий |
Отправлено: 25.04.2004, 22:46 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
|
|
Deem |
Отправлено: 29.04.2004, 09:56 |
|
Мастер участка
Группа: Участник
Сообщений: 327
|
Если работало хреново и тормозило, то его по любому надо было переделывать. Другое дело: кому и с каким результатом? Плюс премия за выигрыш
|
|
|