Complete.Org: Mailing Lists: Archives: freeciv-ai: April 2004:
[freeciv-ai] Re: FreeCiv brief analysis
Home

[freeciv-ai] Re: FreeCiv brief analysis

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Guillermo Lopez Alejos <100030179@xxxxxxxxxxxxxxx>
Cc: Raimar Falke <i-freeciv-lists@xxxxxxxxxxxxx>, freeciv-ai@xxxxxxxxxxx
Subject: [freeciv-ai] Re: FreeCiv brief analysis
From: Ross Wetmore <rwetmore@xxxxxxxxxxxx>
Date: Thu, 08 Apr 2004 03:54:46 -0400


Guillermo Lopez Alejos wrote:

Hi,

I've been busy these day so I couldn't write before.


Maybe this become clear if I show you the alternatives:

If the common client controls the interface
 the common client would looks like this:
   forever:
     wait for packet
     process packet (this updates the internal state)
     notify external program
         (if the external program returns here or unlock the common
         client would continue and wait for the next packet)

 the external program may look like this:
   notify_from_common_client_core():

     lock common client
     query client
     calculate
     issue commands
     unlock common client

This lock block is full of false assumptions that will lead to all kinds
of hard to track down bugs, which is why trying to simply port functional
code into a distributed environment usually fails miserably.

Since the actual game state is server controlled, whether you "lock"
the client or not, commands will still be issued in a "stale" environment and thus need to be designed for proper failure modes. Failures push all
the way back to the external program with the extra level of network
separation now, i.e. explicit failure checks are missing in the above.

So build the networking failure modes and delays into the queries from the
start. Queries that are order dependent should be handled by the client
sending a block of ordered results rather than as an inefficient multi-part
request. Stale data re-requests is the other way to handle multi-part,
i.e. if some critical state changes, invalidate and restart the process
(usually) under the assumption that restarts are infrequent.

But note the client can keep a cache of results+data at a given mark point,
while still processing the server updates into the main datastore. The
ezternal program would ask for sequential data "at a given mark point"
(Raimar's snapshot) to in essence "lock" the client. It then "unlocks" /
updates its mark point (or issues a global client cache reset) when it
is done and needs fresh data. This sort of model avoids locking from the
wrong end of the dog and all the inconsistencies and deadlocks that causes.

nikodimka said that this is the correct schema.

I understand the reasons for locking the client (I have followed this
thread) but I wonder if we can hide the locking of the client to the
external program.

Yes in what you want to do, no in the idea of "hiding" at the client.

We can define a turn-based-locking:
    1. puppeteer locks the client
         opens a new transaction environment at the client.
    2. The external program issues its commands (some of them would
require to ask the server and change client's state; in this case the
client may be unlocked and locked again by puppeteer automatically)
         transaction environment can be updated
    3. Finally puppeteer unlocks the client at the end of the turn of
the external program.
         ditches the transaction, aka executes and closes it.

Change this from "client" to "instance of client" where instance is
another word for local snapshot and I think it can run without locks.


Another advantage of this is that multiple puppeteers can run simultaneously
processing different packets/actions/high-level tasks, since snapshot data
is local, as opposed to the main client datastore that is global. There
actually is a "lock cycle" when building a snapshot, and one can use queues
or rendezvous targets to order processing of snapshots in the client. Thus
longterm evolutionary possibilities of the subsystem is quite rich.

Note that the external program has to remain locked when waiting for
client response... hum... how can we release the external program from
doing this explicit? RPCs?

There are at least two types of exchanges occuring between the external
and client programs as well as client/server updates and other "threads"
of program flow.

Always think of conceptual things in terms of threads, and leave the
implementation details of how to manage/synchronize exchanges to the
implementation step assuming there are many ways to do this.

Function call/RPC/http_request-response/... are all conceptually equivalent
though implementationally quite distinct with different robustness and
performance aspects or scope.

--
Guillermo López Alejos - N.I.A. 100030179
Universidad Carlos III de Madrid
Ingeniería Técnica en Informática de Gestión

Cheers,
RossW
=====




[Prev in Thread] Current Thread [Next in Thread]