Author Topic: Two questions about the server  (Read 2318 times)

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
Two questions about the server
« on: July 18, 2004, 06:44:07 am »
1) Error while the server dealing the dabase.

The server can initialize the database, but it shuts down quickly afterwards. The database shows the error as follows.

Aborted connection 1 to db: \'planeshift\' user: \'planeshift\' host: \'localhost\' (Got an error reading communication packets)

I trace into the code and find that the error always comes after the first dealing of the database, ie. after the processing of combatmanager:

combatmanager = new psCombatManager(database,
                                        celserver,
                                        msghandler,
                                        eventmanager);
CPrintf(\"Started Combat Manager...ok!\\n\");

So, when the next dealing the database,

weathermanager = new WeatherManager(database,
                                        msghandler,
                                        eventmanager);
weathermanager->Initialize();
CPrintf(\"Started Weather Manager...ok!\\n\");

the error occurs. How should it be solved?

2) The maximum number of connections

According to the psserver.cfg,

; Maximum number of concurent connections
Planeshift.Server.User.connectionlimit = 20

the default connection limit is 20. What is the maximum number a server can accept?

Thanks in advance!
« Last Edit: July 18, 2004, 06:48:46 am by yesure »

Karosh_Steinkatz

  • Hydlaa Citizen
  • *
  • Posts: 486
    • View Profile
(No subject)
« Reply #1 on: July 18, 2004, 09:14:32 am »
1) Have you created the database? If not, do the following:
Quote
from the cvs howto

planeshift$ mysql -u root
mysql>GRANT ALL PRIVILEGES ON *.* TO planeshift@localhost IDENTIFIED BY \'planeshift\' WITH GRANT OPTION;
mysql>quit
planeshift$ cd planeshift/src/server/database/mysql/
mysql$ mysql -u planeshift -pplaneshift
mysql> source create_all.sql;
mysql> quit


2) I think this number is an example and a safe value, since the capacity of the server hasn\'t been fully tested yet afaik.


Back to Planeshift again \\o/

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
(No subject)
« Reply #2 on: July 18, 2004, 04:04:17 pm »
1) Yes, the database has been created already. All the procedures are according to the manual and of course your statement. But how strange the server is! It cannot run properly.

2) Does the Laanx run the same server program? If a server only can handle 20 clients safely, I wonder there might be over one hundred of computers for the Laanx to maintain a persistent world. Am I right?

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
(No subject)
« Reply #3 on: July 19, 2004, 12:48:06 pm »
After a little exhausting working, I find the exact error source finally. When the server goes to initilalize the weather manager, the error occurs from the computation of the si->raindurationrange and so on.


void WeatherManager::Initialize()
{
    iResultSet *rs = database->GetAllSectorInfos();
 
     if (!rs)
        return;
   
    unsigned int i;
    for (i=0; iCount(); i++)
    {            
        SectorInfo *si = new SectorInfo;

        si->name = (*rs)[\"name\"];  
       
        si->raindurationrange = 1000* (atoi((*rs)[\"rain_max_duration\"]) - atoi((*rs)[\"rain_min_duration\"]));      
        si->raingaprange      = 1000 * (atoi((*rs)[\"rain_max_gap\"])      - atoi((*rs)[\"rain_min_gap\"]));
        si->raindropsrange    = atoi((*rs)[\"rain_max_drops\"])           - atoi((*rs)[\"rain_min_drops\"]);    
        si->lightninggaprange = 1000 * (atoi((*rs)[\"lightning_max_gap\"]) - atoi((*rs)[\"lightning_min_gap\"]));
        si->rainminduration   = 1000*atoi((*rs)[\"rain_min_duration\"]);    
        si->rainmingap        = 1000*atoi((*rs)[\"rain_min_gap\"]);
   si->lightningmingap   = 1000*atoi((*rs)[\"lightning_min_gap\"]);
        si->rainmindrops      = atoi((*rs)[\"rain_min_drops\"]);

        sectors.Push(si);  // Add to array
    }
    ...
}

Currently I cannont figure out how comes. But I\'ll do my best to.

Karosh_Steinkatz

  • Hydlaa Citizen
  • *
  • Posts: 486
    • View Profile
(No subject)
« Reply #4 on: July 19, 2004, 12:48:16 pm »
I searched for the error message, but didn\'t find anything valuable. But I\'m almost sure it\'s a MySQL problem. Maybe your configuration isn\'t correct?

And for the connection limit: Highest number of people online was ~50 afaik, so don\'t worry about the capacity. Like I said, it\'s just a safe default value.


Back to Planeshift again \\o/

Androgos

  • Guest
(No subject)
« Reply #5 on: July 19, 2004, 07:51:48 pm »
Be sure that your mysql.dll is up to date

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
(No subject)
« Reply #6 on: July 20, 2004, 07:21:19 am »
My database is the latest and stable one. In fact, I just downloaded it one or two weeks ago.

Now I\'m pretty sure that the error comes from the server code itself instead of the database.

I\'ve consulted the manaul of MySQL for the communication errors, and find these:


A.2.10 Communication Errors and Aborted Connections
...
If Aborted connections messages appear in the error log, the cause can be any of the following:

The client program did not call mysql_close() before exiting.
The client had been sleeping more than wait_timeout or interactive_timeout seconds without issuing any requests to the server. See section 5.2.3 Server System Variables.
The client program ended abruptly in the middle of a data transfer.


The third cause fits this senario. So the sequence is the server catches an error and shuts down abruptly followed by disconnecting to the database and then the database shows the error.

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
(No subject)
« Reply #7 on: July 21, 2004, 12:22:06 pm »
I\'ve got further finding.

The function, database->GetAllSectorInfos() , in the WeatherManager::Initialize(), didn\'t return correct data!!! So the following computations all get errors.

Keep tracing, slowly but steady...

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
[Progress Report] The bug is coming out
« Reply #8 on: July 26, 2004, 07:05:29 am »
To confirm that the database is working, I wrote a simple program to try to retrieve the data from the database.

main.cpp:
#include \"data.h\"
#include
#include

void main()
{
  MYSQL        *conn;
 MYSQL_RES    *rs;
   MYSQL_ROW    rr;
    MYSQL_FIELD  *fields;  
    char         *querystr;

 conn = mysql_init(NULL);
    conn = mysql_real_connect(conn,
     \"127.0.0.1\", // host
      \"planeshift\",// user
      \"planeshift\", //pwd
       \"planeshift\", //database
      0, NULL, 0);

    querystr = \"Select * from sector_info\";
   mysql_query(conn, querystr);

    rs = mysql_store_result(conn);
                fields = mysql_fetch_fields(rs);

  for(int row=0; row < mysql_num_rows(rs); row++)
 {
       mysql_data_seek(rs, row);
       rr = mysql_fetch_row(rs);

       for(unsigned int field=0; field < mysql_num_fields(rs); field++)
        {
           printf(\"Row %d: Field %d is %s\\n\", row+1, field+1, rr[field]);
     }
   }

   mysql_free_result(rs);
  mysql_close(conn);
}

data.h:
#define __LCC__
#define __WIN__

No suprise. The database works very well.
But then I modified the function printf() like this:

printf(\"Row %d: Field [%s] is %s\\n\", row+1, fields[row].name, rr[field]);

The program crashes!! How comes \"fields[row].name\" can not do its job??

So there is a strong hint that a bug hides in the original code in psResultRow::operator[] in the dal.cpp, although it seems logical:

const char *psResultRow::operator[](const char *fieldname)
{
    CS_ASSERT(fieldname);
    CS_ASSERT(max); // trying to access when no fields returned in row! probably empty resultset.

    if (!fields)
    {
        fields = mysql_fetch_fields(rs);
    }
   
    for (int i=0; i    {
      if (fields.name && !strcasecmp(fields.name, fieldname))
       {
           return rr;
       }      
    }
     return \"\"; // Illegal name.  
}
« Last Edit: July 26, 2004, 12:42:02 pm by yesure »

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
Bug Caught
« Reply #9 on: July 26, 2004, 04:08:02 pm »
Now, the game is over. The bug hides in libmysql.lib and is caused by MYSQL_FIELD from the version 4.0.20a of mySQL.

I have to apologize to the authors of the server code and all the readers of this thread sincerely for my stupid and stubborn manner and thank Karosh and Androgos also.

All I have gained is unforgettable debugging experience and learned much from the code and the database.

Thank you all, thank you very much!

Bye!

calloc

  • Wayfarer
  • *
  • Posts: 3
    • View Profile
(No subject)
« Reply #10 on: July 26, 2004, 05:50:48 pm »
There is a memory leak in that part of the code.  The psserver program exits with a segmentaion fault on startup on my sytem.  I managed to trace the memory leak to the same function as you did.

const char *psResultRow::operator[](const char *fieldname)  in  \"/src/server/database/mysql/dal.cpp\"

The problem is the memory that the fields* is pointing to is being released at some point. I wrote a quick fix that buffers the field names and now no more memory leak.  Unfortunately I don\'t have write access to the repository to upload the fix.

« Last Edit: July 26, 2004, 05:58:42 pm by calloc »

calloc

  • Wayfarer
  • *
  • Posts: 3
    • View Profile
(No subject)
« Reply #11 on: July 26, 2004, 07:48:17 pm »
Heres a quickfix.  I only just recently downloaded and compiled the source and haven\'t been able to do much testing.  I\'ve got as far as the character creation screen now, but apparently i need to download some missing graphic files.

Replace function with,

const char *psResultRow::operator[](const char *fieldname)
{
    CS_ASSERT(fieldname);
    CS_ASSERT(max); // trying to access when no fields returned in row! probably empty resultset.
    CS_ASSERT(MAX_TABLE_FIELDS > max); // if assert on startup, increase MAX_TABLE_FIELDS.
   
    int i;
    // If not stored, store or all field names.
    if( !fields )
    {
        for (i=0 ; i < max ; i++)
        {
            if(( fields = mysql_fetch_field (rs)) != NULL) {
                 strcpy(field_buffer, fields->name);
            } else CS_ASSERT(0);
        }
    }

    // search for specified field name in temp buffer.      
    for ( i=0 ; i < max ; i++ )
    {  
        if (!strcasecmp(field_buffer,fieldname))
        {  
            return rr;
        }
    }
    printf(\"Could not find field %s!. Exiting.\\n\",fieldname);
    CS_ASSERT(false);
    return \"\"; // Illegal name.
}

Add the lines below to dal.h

#define MAX_TABLE_FIELDS 100

char field_buffer[MAX_TABLE_FIELDS][60]; <-- put in public section

It would probably be to make field_buffer private and add some handlers or better yet replace arrays with something more efficient.

calloc

  • Wayfarer
  • *
  • Posts: 3
    • View Profile
(No subject)
« Reply #12 on: July 28, 2004, 07:40:32 pm »
It seems the bug only occurs from using a later version of MYSQL. I\'m using an alpha version 5.0.  That versions is releasing the MYSQL_FIELD data, when the next row is read, while apparently older versions of MYSQL don\'t.  
« Last Edit: July 28, 2004, 08:27:26 pm by calloc »

yesure

  • Traveller
  • *
  • Posts: 21
    • View Profile
(No subject)
« Reply #13 on: July 29, 2004, 03:59:25 pm »
Quote
Originally posted by calloc
It seems the bug only occurs from using a later version of MYSQL. I\'m using an alpha version 5.0.  That versions is releasing the MYSQL_FIELD data, when the next row is read, while apparently older versions of MYSQL don\'t.  



Yes. Previously I used version 4.0.20a and got error. Now I use version 4.1.3-beta. It works fine. Maybe you might try this one. The bug is from the libmysql.lib and makes MYSQL_FIELD read the first row of data only.

josephoenix

  • IRC Op
  • Hydlaa Notable
  • **
  • Posts: 706
    • View Profile
(No subject)
« Reply #14 on: July 29, 2004, 04:21:15 pm »
Quote
Originally posted by yesure
Now, the game is over. The bug hides in libmysql.lib and is caused by MYSQL_FIELD from the version 4.0.20a of mySQL.

I have to apologize to the authors of the server code and all the readers of this thread sincerely for my stupid and stubborn manner and thank Karosh and Androgos also.

All I have gained is unforgettable debugging experience and learned much from the code and the database.

Thank you all, thank you very much!

Bye!


I had to burst out laughing there... Your manner was not anywhere _near_ stubborn or stupid, you seemed to know what you were doing, and if you want to see stubborn and stupid you should see posts that amount to

Quote

newbie: \'my planetshift say it is teh deadlink?! fix plz!!!!!\'
oldbie: \'Check the forums for help means read the forums, not post on them looking for help.\'
newbie: \'u r teh not help me! X( anyone help? bsides this not helpful prson????\'


Sad, isn\'t it.


FYI: you can often get a quicker answer from the developers in the developer channel (#planeshift on freenode)

josePhoenix
Sir John Falstaff: "Let the skie raine Potatoes: let it thunder, to the tune of Greenesleeues"