[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference noted::hackers_v1

Title:-={ H A C K E R S }=-
Notice:Write locked - see NOTED::HACKERS
Moderator:DIEHRD::MORRIS
Created:Thu Feb 20 1986
Last Modified:Mon Aug 03 1992
Last Successful Update:Fri Jun 06 1997
Number of topics:680
Total number of notes:5456

282.0. "Help setting up fast server?" by ALIBUT::SANTIAGO (Ed Santiago) Tue Aug 05 1986 17:23

I need to set up a server for a database. I also need to do it in one week,
but that's beside the point. Anyway the situation is as follows:

There is a database on FOO. People in different places (within our area)
need to access information there. Several people. At once. No problem
so far... the thing is, it has to be blazingly fast so that rules out
internode file sharing, server creation by TASK, and $CREPRCing. In
other words, the server has to be a known DECNET object all roarin'
and ready to go, and it has to do all the work itself (ie can't create
subprocesses and let each one bind itself to a remote user).

In other words, I have to hack up a scheduler.

I have given this much thought. I've spent one week asking people
and dreaming up ways to do it, to no avail. As a last desperate
attempt I ask of you: HELP!!!!

Does anybody know how NOTES and VTX manage to do it? Does anybody
have any suggestions? There are an ungodly amount of variables
that need to be kept track of between context changes; I thought of
just declaring everything as an array and having each "process" get
assigned a different handle to its own variable space. So context
switching, although ridiculously gross, looks like it should work.
The problem is how to get somebody to delegate CPU to each sub-job.
Using interrupts might not be the best way, since if the machine is
heavily loaded all the CPU will go to the scheduler and I lose big
time. Having each process decide when to go to sleep won't work
either, since there are some routines where it can get stuck looping
or block for a long time and it's difficult to determine beforehand
where and when this is going to happen. Anyone know of any other
way to do it? Any suggestions or pointers to sources of information
or existing code will be greatly appreciated.

And now, one final question: Is it worth it? I am increasingly of the
opinion that even assuming I can come up with something it's still
going to be much faster to just have VMS create a process for all
incoming requests, since it's merely a one-time overhead upon
invocation of the program and after that everything will definitely
go much much faster. After all, that's what OS's are for, no?

Incidentally, if you can think of any way to create a server meeting
the speed and multiuser criteria without going into brewing up some
sort of scheduler, please let me know! I'm desperate!

Many thanks in advance,				\Ed
T.RTitleUserPersonal
Name
DateLines
282.1CAFEIN::PFAUI brake for ferretsTue Aug 05 1986 18:1025
    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::HESTERMANScott HestermanTue Aug 05 1986 20:1312
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.3How to write a multi-threaded serverSMAUG::GARRODWed Aug 06 1986 01:4693
    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::BYRNEWe apologise for the inconvenienceWed Aug 06 1986 05:527
	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.5DASL might be of some helpXANADU::MORGANWed Aug 06 1986 09:5011
    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.6Try ISLFROST::HARRIMANyou want it when?Wed Aug 06 1986 10:0612
    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.7AK1A::SANTIAGORoads? Where we&#039;re going we don&#039;t NEED roads!Wed Aug 06 1986 13:1749
    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.8More on NETSERVERSMAUG::GARRODWed Aug 06 1986 17:2216
    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.9IT JUST MIGHT DO THE JOB60588::DAVIESMichael NichollsWed Aug 06 1986 21:2926
    
    

    
    
    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.10WRONG NAME60588::DAVIESGrant DaviesWed Aug 06 1986 21:321
    Ops... My name is really Grant Davies... it's now fixed