Archived

This forum has been archived. Please start a new discussion on GitHub.

Can a server close all its connections on request?

Hello. Is it possible to make the server close all its current connections to clients? I read the chapter 35.5 about the connection management. I saw there that I can access the connection object from within each operation, using Ice::Current passed to this operation. But this connection object would be responsible for the connection to this particular operation (handling a particular request as I understand). So I can close the connection to this particular operation using the void close(bool force) function of the connection object. But all the connections to other operations will not be closed.

What I need is some operation which closes all connections to all servants the server is currently maintaining.

Regards
Ewgenij

Comments

  • bernard
    bernard Jupiter, FL
    Hi Ewgenij,

    If you just want to make your servants unreachable for a while, I'd recommend to manage these servants with a Servant Locator ... and then you can easily make them disappear for a while.

    Also, in general, closing a connection does not prevent a client from reconnecting immediately (or a new client from establishing a new connection).

    Could you describe what you're trying to achieve? Are your clients connecting to your server through a Glacier2 router?

    Best regards,
    Bernard
  • Hello.
    If you just want to make your servants unreachable for a while, I'd recommend to manage these servants with a Servant Locator ... and then you can easily make them disappear for a while.

    If I would make the servants unreachable, the currently processed requests would finish properly. The new requests wouldn't be dispatched anymore. But what I want is, that after arrival of the signal S (after a call to some function) all pending and currently executed requests would abort / break / die:) As if somebody has cut the appropriate wires.
    Also, in general, closing a connection does not prevent a client from reconnecting immediately

    Does that mean that if a client makes a call to the server to invoke some operation, and during the execution of that operation the connection would be closed due to some circumstances (for example somebody cuts the wires), the client would try to reestablish the connection?
    Could you describe what you're trying to achieve?

    What I'm triing to achieve is the following:

    The server serves the clients. But if it gets the signal S, then it knows that its information which is used for servicing the client requests, is not up to date. So the clients, served currently, are getting a not up to date service. So the best way would be to close all the connections - the clients would get the ConnectionLostException. After the execution of appropriate routines the server becomes available for the clients again. If any clients attempt to connect in the meanwhile, I could put them on the service queue by a locking mechanism.
    Are your clients connecting to your server through a Glacier2 router?

    That was not planned. But Glacier2 could be used if it would help.

    Greetings
    Ewgenij
  • Ewgenijkkg wrote: »
    But what I want is, that after arrival of the signal S (after a call to some function) all pending and currently executed requests would abort / break / die:) As if somebody has cut the appropriate wires.

    In other words, you want currently-executing operations on the server side to terminate prematurely? If so, you have to arrange for that to happen yourself, that is, you would have to poll for the signal in each operation and cause it to terminate prematurely, probably by throwing an exception or returning some other "failed" indication to the client. The Ice run time cannot terminate executing operations in the server for you because there is simply no mechanism to do so: the thread of control at that point is in the hands of the application code, and Ice cannot simply cancel an executing thread because that would, in general, cause undefined behavior.
    Does that mean that if a client makes a call to the server to invoke some operation, and during the execution of that operation the connection would be closed due to some circumstances (for example somebody cuts the wires), the client would try to reestablish the connection?

    When the connection goes down, the client will see a ConnectionLostException for its current invocation. However, the next invocation made by the client will transparently try to re-establish a connection.

    In general, Ice will retry failed requests, but only if it can be sure that doing so will not cause a single operation invocation by the client to cause the operation to execute a second time in the server. In other words, Ice provides at-most-once semantics for invocations: a single invocation by a client will cause the corresponding operation in the server to run, or will not work at all. However, a single invocation by a client is guaranteed not to cause the operation to run a second time in the server.

    You can modify this behavior with idempotent Slice keyword. If you use that keyword, Ice is more aggressive in its retry behavior and will re-issue a failed request even if there is a chance that doing so might cause a single invocation by the client to invoke the operation more than once in the server. Obviously, you can use the idempotent keyword only for operations that are stateless and free from side-effects.

    If you use UDP as your transport, Ice does not provide at-most-once semantics because UDP can duplicate packets on the network.
    What I'm triing to achieve is the following:

    The server serves the clients. But if it gets the signal S, then it knows that its information which is used for servicing the client requests, is not up to date. So the clients, served currently, are getting a not up to date service. So the best way would be to close all the connections - the clients would get the ConnectionLostException. After the execution of appropriate routines the server becomes available for the clients again. If any clients attempt to connect in the meanwhile, I could put them on the service queue by a locking mechanism.

    You could put the adapter in the holding state, forcefully close the connection for all executing operations and, once the server is ready again, activate the adapter again.

    However, a cleaner way would be to put the adapter in the holding state, throw a user exception from each operation, and then reactivate the adapter once the server is ready. At least, that way, the client gets a proper user exception that indicates why the server is not available at the moment, instead of a ConnectionLostException, which will also be raised for real connection loss (not caused by the server forcefully closing the connection).

    At any rate, to implement what you want, you need to have active participation in both the operation implementations (which must react to the signal) and the clients (which must react to an exception).

    If you want to make this completely transparent on the client side, the only other option I can see is to prevent all operations that are executing at the time the signal arrives from completing. In other words, on receipt of the signal, the operations go to "sleep" until the server gets back to its available state. At that point, the operations would use the new state of the server to resume and then return. That way, clients would simply see a normal successful request that just happens to take a longer time than usual.

    Note though that this approach may not be feasible if the outage time is long. Also, writing your operation implementations to restart in this fashion may not be feasible, depending on what the operations are doing.

    Cheers,

    Michi.
  • Hello!
    You could put the adapter in the holding state, forcefully close the connection for all executing operations and, once the server is ready again, activate the adapter again.

    I thought about this possibility but I couldn't find a way to "forcefully close the connection for all executing operations" of the adaptor. How can you achieve that? I saw only the possibility to close connection for one operation from within this operation.
    However, a cleaner way would be to put the adapter in the holding state, throw a user exception from each operation, and then reactivate the adapter once the server is ready.

    So that means that while each particular operation proceeds I have to check continuously the abort condition. What would be the best way to do this? Something like:
    void operation(bool* shouldAbort)
    {
          code block;
    
          if(*shouldAbort){
                 put the adaptor in the holding state;
                 throw Exception;
                 close the connection;        
          }
    
          code block;
    
          if(*shouldAbort){
                 put the adaptor in the holding state;
                 throw Exception;
                 close the connection;        
          }
    
          code block;
    }
    
    Or is there a smarter way to check continuously for a condition, than to hardcode the check after every X lines of operation code?:)

    Regards
    Ewgenij
  • Ewgenijkkg wrote: »
    I thought about this possibility but I couldn't find a way to "forcefully close the connection for all executing operations" of the adaptor. How can you achieve that? I saw only the possibility to close connection for one operation from within this operation.

    That's right. You can close only the connection for a particular invocation because the connection is provided by the Current object of an operation.
    So that means that while each particular operation proceeds I have to check continuously the abort condition. What would be the best way to do this?

    I would probably monitor the unavailable condition from a separate thread and set a flag when that happens, as well as put the adapter into the holding state. If you can afford to let currently-executing operations complete, the easiest thing would be to test the flag just before the operation returns. You could do that with a simple helper function. Something like:
    void throwIfUnavailable()
    {
        IceUtil::Mutex::Lock lock(unavailableMutex);
    
        if(unavailable)
            throw UnavailableException;
    }
    

    The unavailableMutex and unavailable variables could be static, or a member of the servant class, or whatever is appropriate.

    In the operation implementation, yoiu would then insert the throwIfUnavailable() call in a appropriate places. Putting the adapter into the holding state would be done by the thread that sets the flag, not in the operation implementation. There is no need to close any connections and you can just put the adapter into the holding state and activate it again later. (This prevents new client requests from entering servants while the not available condition lasts.

    Cheers,

    Michi.
  • OK, thank you very much, guys. It was a big help for me :)