T.R | Title | User | Personal Name | Date | Lines |
---|
282.1 | | CAFEIN::PFAU | I brake for ferrets | Tue Aug 05 1986 18:10 | 25 |
| I've worked on a similar type of server with a customer before.
The easiest way to do it as as follows:
Your main-line code should look like this:
hiber: $hiber_s ;wait for incoming message
again: remq ;remove a packet from the queue
bvs hiber ;overflow set means queue is empty
;process packet
jmp again ;get next packet, if any
Do all DECnet receives at AST level. Insert the received information
into a queue and wake the main-line code.
In processing the packet, you have to determine who sent the packet
so you will be looking at the right user's environment. If a new
connection, create a new environment. You can either use LIB$VM
to handle an unlimited number of links or static buffers for a fixed
maximum. This method is pretty responsive as long as you don't
take too long to handle packets.
There is an example in the 'Guide to Networking on VAX/VMS' on page
8-65 which can be used as a template.
tom_p
|
282.2 | (correction page=8-45 in 4.4) | CANYON::HESTERMAN | Scott Hesterman | Tue Aug 05 1986 20:13 | 12 |
| RE Note 282.1 by CAFEIN::PFAU
> There is an example in the 'Guide to Networking on VAX/VMS' on page
> 8-65 which can be used as a template.
In my V4.4 manual its page 8-45, (not 8-65), and I'm not
certain it works... I've been fooling with with the example for
'Nontransparent Communication Using System Services'
and there are some ommissions, typos, and such.
The basic ideas presented therein appear to be correct, however.
|
282.3 | How to write a multi-threaded server | SMAUG::GARROD | | Wed Aug 06 1986 01:46 | 93 |
| You haven't really supplied enough information to answer this question.
In order to give you a full answer you need to answer the following
questions:
1, What sort of database access?
2, How is the database being accessed?
3, Does the database access method have an asynchronous interface?
4, How many concurrent users do you expect?
5, What frequency will DECnet connects come in at?
First of all don't rule out separate VMS processes. If you expect
less than 100 concurrent users (8800) 20 concurrent users (microvax)
set up permanent NETSERVERS for the expected amount of concurrent
users. In this way you won't incur the REALLY expensive process
startup overhead each time a DECnet Connect comes in.
Make sure the image that you run is installed /HEADER_RESIDENT/SHARED
and that all shareable images it is linked against are also installed
/SHARED. This will ease the hit on physical memory. This solution
should only be ruled out if one of the following is true:
1, There are 100s of concurrent users ie you can't spare a process
slot for each user. To be honest if this is the case you are
probably up shits creek anyway even if the users are idle most
of the time due to the amount of non paged pool needed for the
zillions of DECnet logical links.
2, Your database doesn't allow concurrent access by multiple processes.
Assuming you have ruled out the above its on to a multi threaded
server. I basically suggest the approach that the previous reply
gave except there are some simplificatons possible. Here are the
salient points of coding a multi threaded server:
Main line
---------
Declare yourself as a network object specifying an AST routine to
call when a CONNECT arrives
$HIBER;
$EXIT;
END;
Don't bother with a queue of events. Let VMS do your event scheduling
with its AST queue.
Have a block indexed by access number ie each user gets a block
with data structures for that user. Obviously this involves knowing
the max number of users a compile time. If you don't know that
LIB$GET_VM a block of memory when the DECnet CONNECT arrives. Use
the address of this block as a handle for thar user/connect. You
may also want to INSQUE this block into a linked list of current
users.
When the DECnet CONNECT arrives the AST routine accepts the connect
and sets off the first operation you want to do. Presumably an
asynchronos READ QIO on the DECnet logical link. Give an AST routine
address to this QIO and the ASTPRM is the address of the user block
LIB$VMed above or the blockvector index if you are using a static
blockvector. Now return from the AST. You are now back at the $HIBER.
When the receive QIO completes your AST routine fires and the ASTPRM
gives you your context ie a handle into this users data structure.
In this AST routine do all you can SYNCHRONOUSLY. When you get to
an operation that won't complete in a SHORT period of time kick
off another asynchronous operation with an AST routine and the ASTPRM
as described above.
Keep state information in your user specific data structure. In
that way when you enter an AST routine you'll know what just happened/
needs to be done next etc. The sort of thing you might store is
the next record number to read, the state of the DECnet logical link,
what the vicar had for tea (crumpets maybe?) etc.
The key thing in the above is that your AST routine cannot execute
an operation that hang indefinitely (or even for a significant period
of time) because while that thread is hanging no other thread can
do anything.
There is also a popular misnomer that AST routines mustn't do much.
This just ain't so! Do as much as you can from AST entry to AST
exit. Only exit from the AST when you need to do something that
would require waiting. Typically the last thing you do is kick off
another asynchronous action. The AST of which will be called later.
Meanwhile you return to the $HIBER and ASTs for other threads fire
up. There is absolutely no harm in the AST routine executing for
a long time AS LONG AS IT IS CPU BOUND. You're going to need to
expend that CPU anyway so it makes no difference whether it is done
now or later and that while it is being expended ASTs for other
threads are queueing up.
Let us know how you get on.
Dave
in the array
|
282.4 | *>- @ -<* | SWIFT::BYRNE | We apologise for the inconvenience | Wed Aug 06 1986 05:52 | 7 |
| Just a thought. VAX DSM can access a remote database
(structure file) via Ethernet. Don't ask me how but
it works; without the aid of a safety net.
Cheers,
Ciaran.
|
282.5 | DASL might be of some help | XANADU::MORGAN | | Wed Aug 06 1986 09:50 | 11 |
| Just a quick pointer - a DEC internal "product" called DASL exists
that is layerd on top of DECNET. DASL will take care of all the
down and dirty task-to-task communication for you, and will set
up session context for you. The VTX server is layered on top of
DASL. For more information, there is a DASL notes file that can
be found in MANANA::DSL. The DASL notes file also has complete
examples of how to write a client and server.
P.S. Good luck getting your task done in a week!
john
|
282.6 | Try ISL | FROST::HARRIMAN | you want it when? | Wed Aug 06 1986 10:06 | 12 |
| Also there is a DEC internal product called ISL which we are using
that does essentially the same thing. The contact for that is Ted
Macomber in Concord (I don't have his node or location but ELF might).
ISL is very easy to use; i.e. you don't have to spend much time
putting things together since it has functions for setting up all
of the non-transparent communications... Also it keeps session context
straight, don't ask me how, but I know it works. We are running,
in production, a real-time WIP status server/client facility between
INFINET and MAXCIM which uses ISL extensively. (It works too!)
/pjh
|
282.7 | | AK1A::SANTIAGO | Roads? Where we're going we don't NEED roads! | Wed Aug 06 1986 13:17 | 49 |
| Thanks all... I looked in the DSL notesfile and am now going to
see if I can get docs for it and for ISL, see how they work.
Probably won't be able to do it in a week; it's not really needed
then but I'm just a summer hire and that's when I'm leaving.
And I hate leaving things halfway done.
Incidentally, the database is a standard indexed file with all
accesses going through RMS. It is very unlikely that more than
ten people would ever be using it at the same time. As a matter
of fact it will probably not get more than 1/2 hour per day of
usage except once a month when billing is done, but since the
project I got hired to do got canned I've been working on this
thing just to keep me off the streets :-).
The way I had originally set it up was using asynchronous QIOs and
$HIBERnating in the meantime. Upon connection request it would assign
the remote user a handle, initialize the database for him/her and
sleep while it waited for commands. Each command would come in through
asynch QIO again and the server would dispatch it to the appropriate
routine while still in AST level. My problem was that most of the
routines take a long time to finish (ex: listing all elements) so if
any requests came in the meantime they would get queued up for a long
time since you can't interrupt an AST already in progress (I think -
I'm a newcomer to VMS and still don't know my way around very well).
Anyway even if you could, what would happen is you'd get a LIFO
situation and whoever put in the first request could get interrupted
forever as other requests came in (not likely but it's still a
possibility). It would also definitely bomb if, say, one "task"
had a record locked and it tried to read it (you lose - can't
read it, can't wait for it to be unlocked!). The suggestions in
.1 and .3 would work if the server was getting talked to a lot,
but unfortunately it's just getting simple one-line requests and
doing all the processing and talking itself. It could probably be
hacked so the heavily CPU intensive stuff (report generating)
would be spawned as an independent subprocess since it's going to
take a long time anyway, and the big LISTs send one item at a time
and wait for the remote to request another, but that would slow
things down considerably (too much traffic on the net if the remote
has to handshake for each element). Also the way the code is set up
now there's a lot of recursion and deep level nesting so returning
to the HIBER isn't so simple. I might end up doing that anyway,
but only if DASL and ISL aren't sufficient.
One more question: How do you set up multiple netservers (.3)? It
sounds like a good idea, but can more than one process declare
itself with the same name? As I said VMS is new to me so please
excuse if it's a stupid question.
Thanks 1E+6 again! \Ed
|
282.8 | More on NETSERVER | SMAUG::GARROD | | Wed Aug 06 1986 17:22 | 16 |
| It sounds to me like you already have the single threaded version
of the application. Given that you'll have less than 10 users permanent
NETSERVERS are the way to go. One process per person.
See DECnet/VAX documentation for info on permanent netservers or
SYS$SYSTEM:NETSERVER.COM. You need to set up a timeout parameter
in the login command file.
The program DOES NOT declare itself as a a network object. You set
up the object database to point at your .EXE file for the object
that the client is trying to activate.
My earlier tutorial and all the notes referring to DASL etc are
only applicable if you need to write a multi-threaded server.
I say it again it looks like you DON'T need to.
Dave
|
282.9 | IT JUST MIGHT DO THE JOB | 60588::DAVIES | Michael Nicholls | Wed Aug 06 1986 21:29 | 26 |
|
This may be useful.
I wrote a network server for an network application we had here in
Sydney Australia. I then presented a session on it and it's uses to
a DECUS VAX workshop. It supports multi-threading if you need it,
although our application was single threaded using RDB.
From reading the other replies to this note, it seems to do exactly
what most people said it should do.
If you wish to have a look at it its on
{SNOV04,SNOV06,SNOV13,SNOV16,SNOV17,SNOV20}""::DISK$CC60J:[DAVIES.DECUS]*.*.*
It's got the transcript on what I said at DECUS that may give you some
pointers, some DECslides of my pictures and a small installation
instructions. I also includes an test example use of it.
|
282.10 | WRONG NAME | 60588::DAVIES | Grant Davies | Wed Aug 06 1986 21:32 | 1 |
| Ops... My name is really Grant Davies... it's now fixed
|