[squeak-dev] Distributing network load using HydraVM

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Distributing network load using HydraVM

Igor Stasenko
My head just visited another idea, and i'd like to share it :)

There was a discussion on how to pass sockets between images safely.
And due to reasons that it's not safe, not easy, and require a lot
changes which may break compatibility, solution was postponed for a
future.

Now, i think i found the way how to pass the newly created socket to
another image by using a special accept primitive.

What this primitive should do:

by taking parameters: interpreter handle, socket handle and channel
name, it should
1. do validity checks (all handles should be valid e.t.c)
2. accept new incoming socket connection (socket handle passed to
primitive should be in listen mode)
3. if system fails with accept(), primitive fails
4. create an event and put new socket handle , and channel name to it.
5. enqueue given event to target interpreter event queue.
--

Event handling:
- register socket handle in SocketPlugin internal structures.
- then find channel with given name, and put SocketHandle bytearray as packet.

voila..

Now at language side, you simply need a channel, which listening for
packets, containing socket handles.
Once packet received, you know, that it's newly accepted socket
connection and can do anything you want with it.

............
by finishing writing this, i just thought that passing ownership of
already open socket can be done in similar way:
a primitive can remove given socket from SocketPlugin internal
structures and pass it with event to another interpreter.

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Distributing network load using HydraVM

Klaus D. Witzel
On Tue, 26 Feb 2008 04:51:56 +0100, Igor Stasenko wrote:

> My head just visited another idea, and i'd like to share it :)
>
> There was a discussion on how to pass sockets between images safely.
> And due to reasons that it's not safe, not easy, and require a lot
> changes which may break compatibility, solution was postponed for a
> future.
>
> Now, i think i found the way how to pass the newly created socket to
> another image by using a special accept primitive.
>
> What this primitive should do:
>
> by taking parameters: interpreter handle, socket handle and channel
> name, it should
> 1. do validity checks (all handles should be valid e.t.c)
> 2. accept new incoming socket connection (socket handle passed to
> primitive should be in listen mode)

Does your 2. correspond to the line I marked in the following?:

| localhost serverSocket clientSocket sessionSocket listener |
  localhost := NetNameResolver localHostAddress.
  serverSocket := Socket newTCP listenOn: 7680 backlogSize: 1.
  listener := [serverSocket waitForConnectionFor: 0.5
        ifTimedOut: [Transcript cr; show: 'timed out ',
        serverSocket statusString]]
    forkAt: Processor activeProcess priority.
  clientSocket := Socket newTCP connectTo: localhost port: 7680.
  (Delay forMilliseconds: 250) wait.
"marked" sessionSocket := serverSocket accept.
  Transcript cr; show: '[server] ', serverSocket statusString;
        cr; show: '[session] ', sessionSocket statusString;
        cr; show: '[client] ', clientSocket statusString;
        cr; show: 'listener: ', listener browserPrintString; cr.
  serverSocket destroy.
  clientSocket destroy.
  sessionSocket destroy

You mean, the marked line would be done by the new primitive, the accepted  
Socket then passed to another HydraVM instance (err, interpreter, via  
channel)?! That would allow "workers" run on their own CPU :)

> 3. if system fails with accept(), primitive fails
> 4. create an event and put new socket handle , and channel name to it.
> 5. enqueue given event to target interpreter event queue.
> --
>
> Event handling:
> - register socket handle in SocketPlugin internal structures.
> - then find channel with given name, and put SocketHandle bytearray as  
> packet.
>
> voila..
>
> Now at language side, you simply need a channel, which listening for
> packets, containing socket handles.
> Once packet received, you know, that it's newly accepted socket
> connection and can do anything you want with it.
>
> ............
> by finishing writing this, i just thought that passing ownership of
> already open socket can be done in similar way:
> a primitive can remove given socket from SocketPlugin internal
> structures and pass it with event to another interpreter.
>



Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Distributing network load using HydraVM

Igor Stasenko
On 26/02/2008, Klaus D. Witzel <[hidden email]> wrote:

> On Tue, 26 Feb 2008 04:51:56 +0100, Igor Stasenko wrote:
>
>  > My head just visited another idea, and i'd like to share it :)
>  >
>  > There was a discussion on how to pass sockets between images safely.
>  > And due to reasons that it's not safe, not easy, and require a lot
>  > changes which may break compatibility, solution was postponed for a
>  > future.
>  >
>  > Now, i think i found the way how to pass the newly created socket to
>  > another image by using a special accept primitive.
>  >
>  > What this primitive should do:
>  >
>  > by taking parameters: interpreter handle, socket handle and channel
>  > name, it should
>  > 1. do validity checks (all handles should be valid e.t.c)
>  > 2. accept new incoming socket connection (socket handle passed to
>  > primitive should be in listen mode)
>
>
> Does your 2. correspond to the line I marked in the following?:
>
>  | localhost serverSocket clientSocket sessionSocket listener |
>   localhost := NetNameResolver localHostAddress.
>   serverSocket := Socket newTCP listenOn: 7680 backlogSize: 1.
>   listener := [serverSocket waitForConnectionFor: 0.5
>         ifTimedOut: [Transcript cr; show: 'timed out ',
>         serverSocket statusString]]
>     forkAt: Processor activeProcess priority.
>   clientSocket := Socket newTCP connectTo: localhost port: 7680.
>   (Delay forMilliseconds: 250) wait.
>  "marked" sessionSocket := serverSocket accept.
>   Transcript cr; show: '[server] ', serverSocket statusString;
>         cr; show: '[session] ', sessionSocket statusString;
>         cr; show: '[client] ', clientSocket statusString;
>         cr; show: 'listener: ', listener browserPrintString; cr.
>   serverSocket destroy.
>   clientSocket destroy.
>   sessionSocket destroy
>
>  You mean, the marked line would be done by the new primitive, the accepted
>  Socket then passed to another HydraVM instance (err, interpreter, via
>  channel)?! That would allow "workers" run on their own CPU :)
>

Yes, approximately.
So, in _another_ image code can look like:

HydraChannel listen: #acceptChannel onData: [:socketHandle |
  | sessionSocket |
   sessionSocket :=  Socket fromHandle: socketHandle.

"we need to check this, because data can come to channel from random source"
   sessionSocket isValid ifTrue: [
         sessionSocket initSemaphores.  "bind new semaphores (read/write/close)"
         [ MyClass startSessionWith: sessionSocket ] fork. " now we
can work with socket"
   ]
]

And at 'dispatcher' side, where you having server socket listening for
connections, it can look like:

interpreter := self selectWorkerWithMinimalLoad.
serverSocket acceptBy: interpreter onChannel: #acceptChannel.

Interesting, that squeakers can implement own
#selectWorkerWithMinimalLoad by any criteria they want, and distribute
threads load by own criteria (assume worker threads passing some
feedback to dispatcher thread). This is unlikely can be achieved using
multiple OS processes setup. In fact, it's nearly impossible :)

--
Best regards,
Igor Stasenko AKA sig.