Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

need help - poll() replaced with VMS services

 
Alex Chupahin
Super Advisor

need help - poll() replaced with VMS services

hello dear all,
I'm working on replacing poll with VMS system service calls.

This is the function for sockets.
input parameters: poll filled structure, an event flag for a something event, sometimes turned on anywhere, a buffer for the data read, and timeout.

poll_with_event_with_read
is wait for a possible read from sockets, or event flag is set. When a socket become ready, it reads a data from it and store into buffer.

First, I put my code,
Next message I describe every block if anybody does not like to grab this junk totally.

This is my full code:

int vms_poll_with_event_with_read(struct pollfd *poll_data, struct fd_buf *buf, int n, int timeout, unsigned event)
{
char time_str[256];
long long vmstimeout;
unsigned long timer_efn;
struct dsc$descriptor_s vmstime_str;
struct dsc$descriptor_s vmsfd_name[n];
unsigned status;
unsigned efn[n];
unsigned short chan[n];
unsigned long long reqidt=0 /*=vaxc$get_sdc()*/;
int ret=0;
char fdname[256];
int mask_flag=0;
struct iosb ios[n];
int i;

/* ---------block1 ---------*/
status = LIB$GET_EF(&timer_efn);

if (n>0)
{
unsigned long long shift=1;
for (i=0;i {
status = LIB$GET_EF(&efn[i]);
check(status);
/*
getname(poll_data[i].fd,fdname);
vmsfd_name[i].dsc$a_pointer = fdname;
vmsfd_name[i].dsc$w_length = strlen(fdname);
status = SYS$ASSIGN(&vmsfd_name[i],&chan[i],0,0,0);
check(status);
*/
chan[i] = decc$get_sdc(poll_data[i].fd);
reqidt += chan[i]*shift;
shift *= 65535;
}
}
else
{
reqidt=0; /*timer id */
}

if (timeout<0)
{
/* infinity timeout, do not set the timer */
status=SYS$CLREF(timer_efn);
check(status);
}
else
{
/* setting the timer, flag is timer_efn */
sprintf(time_str,"0 00:%2d:%2d.00",(int)timeout/60,timeout%60);
vmstime_str.dsc$w_length = strlen(time_str);
vmstime_str.dsc$a_pointer = time_str;
status = SYS$BINTIM (&vmstime_str, &vmstimeout);
check(status);
status = SYS$SETIMR (timer_efn, &vmstimeout, timer_ast, reqidt);
check(status);
}

/*-----------block2 ----------*/
if (n==0)
{
mask_flag=0;
if (event>0)
mask_flag|=1<<(event-32);
if (timer_efn>0)
mask_flag|=1<<(timer_efn-32);
status = SYS$WFLOR(timer_efn,mask_flag); // wait for event or timer_efn
check(status);
status = SYS$READEF(timer_efn,&mask_flag);
check(status);

status = LIB$FREE_EF(&timer_efn);
return (mask_flag & (1<<(event-32)) ) ? 1 : 0;
}
/* --------- block 3 -------- */
mask_flag=0;
for (i=0; i {
if (!buf->buffer)
{
unsigned dummy;
status=SYS$QIO(efn[i],chan[i],IO$_READVBLK,&ios[i], qio_ast, &reqidt, &dummy, 1, 0,TCPIP$C_MSG_PEEK,
0,0);
}
ret=1;
}
/* ---- block 4 ----- */
else
{
status=SYS$QIO(efn[i],chan[i],IO$_READVBLK,&ios[i], qio_ast, &reqidt,
buf[i].buffer + buf[i].off, buf[i].bufsize - buf[i].off, 0,0,0,0);
}
if (!(status & STS$M_SUCCESS))
{
printf("Error CHAPG\n");
}

mask_flag |= 1<<(efn[i]-32);
}
if (event>0)
mask_flag |= 1<<(event-32);
if (timer_efn>0)
mask_flag |= 1<<(timer_efn-32);
/* ----- block 5 ----- */
SYS$WFLOR(timer_efn,mask_flag); // wait for efn[0..n] or timer_efn or event);
SYS$READEF(timer_efn,&mask_flag); //read flags status
/* delete unready I/O queries */
for (i=0; i SYS$CANCEL(chan[i]);
SYS$CANTIM(reqidt,0); // Cancel timer
status = LIB$FREE_EF(&timer_efn);
for (i=0; i {
if ( mask_flag & (1<<(efn[i]-32)) )
{
status=ios[i].status;
buf[i].got_newdata=1;
if ( !(status & STS$M_SUCCESS) )
{
int ret;
This is may be wrong correspond to listen only socket buf[i].buffer==NULL*/
poll_data[i].revents=POLLHUP;
// ret = send(poll_data[i].fd, &n, 0, 0);
// if (!ret || (ret == -1 && errno == EINTR))
// poll_data[i].revents &= ~POLLHUP;
}
else
{
buf[i].off += ios[i].count;
poll_data[i].revents=POLLIN;
ret++;
}
printf("CHAPG %d\n",ios[i].count);

}
else
{
poll_data[i].revents=0;
}
status=LIB$FREE_EF(&efn[i]);
//check(status);
}

status = LIB$FREE_EF(&timer_efn);

if (ret==0)
ret=1; /*it is mean only event flag is set*/

return ret;

}



8 REPLIES 8
Alex Chupahin
Super Advisor

Re: need help - poll() replaced with VMS services

ok.

block 1.
I prepeared a timer with id composed from channel number. When timer is gone, ast timer routine will get this id, decode it and cancel all QIO requests passed to the channels.

block 2.
it is executed when no sockets passed to the routine. So no QIOs, only wait for a timer or the event flag.

For each passed socket:
block 3.
You may not look for it - it is requirement for the main software module - if buffer is NULL - it should do the "virtual" reading.
Do not know exactly what does it mean and what the conclusion.
block4
Executes real QIO. Flag efn[i] should be set when a QIO is completed.
ast routine cancels all QIOs for other channels that may be in queues or executed.

block5.
waiting for any QIO flag, timer and event is set.
Then read flag event claster, checking for flags set, filling out poll structure.

Alex Chupahin
Super Advisor

Re: need help - poll() replaced with VMS services

SAnd this is a question.

This code is worked. Sometimes.
Sometimes not.
network server (this is a part of tcp server)
lost connection. It is depends from a CPU speed of machine code executed and Australia's weather.
I just see a bad places - the time from the event "QIO query is completed" and executing "cancel other QIOs" not equal to 0. So it is a chance that another QIO for another channel is completed before first ast procedure from first QIO delete all another QIOs.

So I'll be very happy to see OpenVMS Master's examples how to work with threaded and timed QIO operations.

Alex Chupahin
Super Advisor

Re: need help - poll() replaced with VMS services

And this code is not *in prodaction* of course, it is only for demostrate the problem.
Alex Chupahin
Super Advisor

Re: need help - poll() replaced with VMS services

May be somebody has a better solution/idea?
It should be very very good if any.
Craig A Berry
Honored Contributor

Re: need help - poll() replaced with VMS services

Are you aware that poll() has been available in the CRTL since 7.3-2?

Alex Chupahin
Super Advisor

Re: need help - poll() replaced with VMS services

Yes, of course.

But if you had read my first message you can see:
1. poll is available nothing exclude sockets.
2. Originally (software I'm porting) poll was used for mixed sockets and pipe as signaled tech.
3. If you see, the routine is named as *poll with event*. So any POLL events behavour should be mixed with an event.

If you can easy mix poll integrated timeout with event please welcome.
Thats topic is devoted to.
Alex Chupahin
Super Advisor

Re: need help - poll() replaced with VMS services

Once more:
may be I'm not describe clearly the problem:

I need a usual poll function with the one event additionally.
i.e.
I should wait for a sockets OR THE EVENT is set for specefied timeout.

It was very good, if anybody point me a good idea how to do it better or (the best) point me to OpenVMS poll sources.
Richard Whalen
Honored Contributor

Re: need help - poll() replaced with VMS services

If the "pipe" is a mailbox then here's an outline for a possible way to write your routine:

Determine if the channel is a socket or mailbox
for socket queue a readattn ast
http://www.openvms.compaq.com/doc/82final/6529/6529pro_026.html#readattn
For a mailbox queue set a read attention ast
ftp://ftp.hp.com/pub/openvms/doc/AA-PV6SG-TK.PDF look in the mailbox driver section for the mailbox function codes.

queue timeout ast
wait for event flag(s)
the Ast(s) set event flags
poll event flags

I haven't done a poll routine, but I've written routines that allowed a select-like function to be done for a combination of sockets, pipes and terminals (slightly more challenging than mailboxes), so this can be done.