logo logo

 Back to main page

The NWNX Community Forum

 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
patchset mnx-timeout: usleep(int)

 
Post new topic   Reply to topic    nwnx.org Forum Index -> Linux development
View previous topic :: View next topic  
Author Message
elven



Joined: 28 Jul 2006
Posts: 259
Location: Germany

PostPosted: Mon Sep 17, 2007 10:32    Post subject: patchset mnx-timeout: usleep(int) Reply with quote

nwnx_mnx suffers from asynchronous timeouts when no timely answer arrives. The calling script has no means of waiting for the answer, because the scripting vm supports no blocking sleep command.

This first easily digestible patchset implements usleep() as a "near-native" nwscript function (nwnx_functions).


First, the C code:
Code:

Index: NWNXFunction.h
===================================================================
--- NWNXFunction.h      (revision 572)
+++ NWNXFunction.h      (working copy)
@@ -68,6 +68,8 @@
        void DebugMe(char* value);
        void ObjDump(char* value);

+       void USleep(char* value);
+
        //unsigned long GetObjectByID();
        unsigned long GetFirstArea();
        unsigned long GetNextArea();
Index: NWNXFunction.cpp
===================================================================
--- NWNXFunction.cpp    (revision 572)
+++ NWNXFunction.cpp    (working copy)
@@ -39,6 +39,17 @@
 {
 }

+void CNWNXFunction::USleep(char* value)
+{
+       int amount = atoi(value);
+       if (amount < 1)
+               amount = 1;
+       if (amount > 5000)
+               amount = 5000;
+
+       usleep(amount);
+}
+
 void CNWNXFunction::SetGoldPieceValue(char* value)
 {
        if (*(pGameObject+0x4) == 0x6) // object type item
@@ -607,8 +618,13 @@
        Log(2,"Request: \"%s\"\n",Request);
        Log(3,"Params:  \"%s\"\n",Parameters);

-       if (strncmp(Request, "SETGOLDPIECEVALUE", 17) == 0)
+       if (strncmp(Request, "USLEEP", 6) == 0)
        {
+               USleep(Parameters);
+               return NULL;
+       }
+       else if (strncmp(Request, "SETGOLDPIECEVALUE", 17) == 0)
+       {
                SetGoldPieceValue(Parameters);
                return NULL;
        }


Now the ingame API:
Code:

Index: nwnx_functions.nss
===================================================================
--- nwnx_functions.nss  (revision 572)
+++ nwnx_functions.nss  (working copy)
@@ -13,6 +13,9 @@
 /* Function prototypes              */
 /************************************/

+// Sleep for usec microseconds.
+void usleep(int usec);
+
 // Get the AC of armor oObject
 int GetArmorAC(object oObject);

@@ -124,6 +127,11 @@
 /* Implementation                   */
 /************************************/

+int usleep(int usec)
+{
+    SetLocalString(GetModule(), "NWNX!FUNCTIONS!USLEEP", IntToString(usec));
+}
+
 int GetArmorAC(object oObject)
 {
     string sAC;


Despite this being a trivial no-brainer, I have not tested it for serious/unknown side effects.

Feedback is, as usual, quite welcome.

The mnx patchset follows shortly.
Back to top
View user's profile Send private message
elven



Joined: 28 Jul 2006
Posts: 259
Location: Germany

PostPosted: Mon Sep 17, 2007 10:44    Post subject: Reply with quote

The patch to mnx is not as easily done, because there is no useable default API present in the linnwnx2 package.

However, whatever your current self-cooked mnx-API is, it better works the way it was designed: Asynchronous operation. For those that have not quite worked that out yet, here is how it works:

* nwserver sends a command to mnx (through SetLocalString)
* mnx answers with a generated unique RECEIPT (probably a timestamp+usec. This is up to _you_)
* nwserver (eventually) requests the results for this command by issuing a "RECIPE!<timestamp>".
* mnx answers by sending the real command answer back to nwserver.

While this is nice in theory, it has two serious limitations, of which I will address one in this patchset:
* There is no identification for answers, or for RECEIPTs. Quickly arriving messages might, because of the statelessness of UDP, not be in order and as such commands might get confused for each other. This is either fixable by using TCP, or by marking every and each message sent with a sequence ID (or using TCP :}).
* nwserver has no way to wait for an answer that takes longer to process than the overhead mnx introduces (switch to mnxlib, send udp packet, retrieve receipt, return receipt to nwserver, switch to mnx, retrieve receipt answer).

For the latter problem, the above usleep() patch was introduced. Patch your mnx library as follows (your code will vary wildy, I guess).

Code:

        // Send the initial command (str)
        string rcp = mnxGetString(str);

        int tries = 0;
        int found = 0;
        while (tries < 6) {
                if ((found = mnxGetAnswer(rcp)) > 0)
                        break;

                usleep(70);

                tries++;
        }
        if (!found)
                // return error 
       
        // process reply



This is mostly theory. I've just implemented it in practice this morning, because I was seeing dropped requests due to the backend being just a tad too slow. I will keep this thread up to date as to how it works out.
Back to top
View user's profile Send private message
elven



Joined: 28 Jul 2006
Posts: 259
Location: Germany

PostPosted: Fri Feb 01, 2008 17:14    Post subject: Reply with quote

Here I've published nearly all mnx core code I've got running in production so far. It is all GPLv3.

It will not run as it is, and it is missing some linnwnx2-code apart from the above usleep-patch. This will be cleaned up and published later, as soon as I can find the time to do so.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    nwnx.org Forum Index -> Linux development All times are GMT + 2 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group