C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
качество кода, нужна критическая оценка
Георгий
Отправлено: 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



Все целиком как-то в голову не лезет. smile.gif Чтоб оценить качество, надо нескольким человекам решить общую задачу по-своему, а потом выбрать оптимальный вариант. А с ним уже сравнивать тестируемый biggrin.gif

Мне не нравиться отсутствие видимых уровней вложенности, читать трудновато. Если работает, думаю — нормально. А ваще, чужой код оцениывать — хуже некуда.

Отредактировано Deem — 23/04/2004, 17:42
Георгий
Отправлено: 23.04.2004, 23:24


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Видимые уровни вложенности были, но после поста все повторяющиеся пробелы в начале строк превратились в один единственный...
читать в таком виде действительно херово...

вариант "до переделки" не мой и не во всех ситуациях работающий корректно.
"после переделки" — мой. переделывал на спор и уложился в 4 рабочих дня. мой вариант работает в 3 раза быстрее не переделанного и во всех тех ситуациях, когда его предок давал сбой, мой держится молодцом smile.gif

( сам себя не похвалишь — никто не похвалит )

PS. про качество я сам сделал вывод — хреновое, раз за 10 дней никто так и не смог разобраться в программе и высказать своё мнение.
Иван
Отправлено: 24.04.2004, 00:16


Машинист паровоза

Группа: Участник
Сообщений: 207



Георгий, извините конечно что вопрос не по теме, но все же,
у вас хватает времени на работе заниматься посторонними делами,или это просто определение "рабочий день"?
Георгий
Отправлено: 24.04.2004, 09:31


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



Хм.. Я системный программист — и программы, подобный приведённой, моё основной занятие. Срочная переделка понадобилась для успешной демонстрации заказщику всеко комплекса ПО, частью которого и является приведённый код.

PS. biggrin.gif так что это не "посторонние дела" , а нормальный рабочий процесс smile.gif

Отредактировано Георгий — 24/04/2004, 10:35
Иван
Отправлено: 25.04.2004, 21:26


Машинист паровоза

Группа: Участник
Сообщений: 207



Извините за, может быть, неточную формулировку,
но я имел ввиду вот что:
QUOTE
переделывал на спор
smile.gif
Георгий
Отправлено: 25.04.2004, 22:46


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



biggrin.gif
Deem
Отправлено: 29.04.2004, 09:56


Мастер участка

Группа: Участник
Сообщений: 327



Если работало хреново и тормозило, то его по любому надо было переделывать. Другое дело: кому и с каким результатом? Плюс премия за выигрыш smile.gif



Вернуться в Аспекты и идеология профессиональной разработки ПО