Solved nQueryMode Invalid

Status
Not open for further replies.

camz29

New member
Registered
Joined
Jun 17, 2024
Messages
21
Solutions
2
Reaction score
1
Points
3
Can someone help me explain why this error exists and how to solve this? Thank you in advance for your help!

1728125219222.png
 
Solution

Issue: Unexpected nQueryMode Values (21 and 0) in IOCP​

Problem:
In the CDbManager :: PutThread function, an invalid nQueryMode is being passed, triggering the default case in the switch:

Hey There!
Please login and(or) register to see this awesome content today.
Hey There!
Please login and(or) register to see this awesome content today.


Why Are These Values Being Sent?​

First, let’s understand what’s happening.

Windows IO Completion Port (IOCP) is used for efficient, asynchronous task handling across multiple threads. It lets the system manage threads waiting for IO operations to complete, helping to avoid the overhead of having too many threads or...

Issue: Unexpected nQueryMode Values (21 and 0) in IOCP​

Problem:
In the CDbManager :: PutThread function, an invalid nQueryMode is being passed, triggering the default case in the switch:

Hey There!
Please login and(or) register to see this awesome content today.
Hey There!
Please login and(or) register to see this awesome content today.


Why Are These Values Being Sent?​

First, let’s understand what’s happening.

Windows IO Completion Port (IOCP) is used for efficient, asynchronous task handling across multiple threads. It lets the system manage threads waiting for IO operations to complete, helping to avoid the overhead of having too many threads or too many context switches. FlyFF utilizes this constantly to split tasks amongst threads to offload incoming network data in to a thread, or request that thread to handle a task. In this instance and most instances, it's to interact with the database to let the database post back.
  • Connection Setup: Several CQuery objects are initialized to handle database connections
  • Task Queueing: The PutThread() function enters an infinite loop where it calls GetQueuedCompletionStatus(), which blocks until an IO task completes or is posted to the IOCP.
  • Task Handling: When a task is posted, GetQueuedCompletionStatus() returns a lpDbOverlappedPlus object that contains details about the completed task. Based on the task type (in nQueryMode), the thread executes the appropriate logic (e.g., saving concurrent user numbers to the database).
  • Thread Management: IOCP allows multiple threads to wait on the same completion port, letting the OS distribute tasks efficiently. The tasks are processed as they complete, avoiding idle time in threads.

Example of Task Posting:​

Here’s how tasks are posted:
Hey There!
Please login and(or) register to see this awesome content today.

It allocates memory for a task, make request copies the ar buffer, and it sets the query mode.

Conclusion​

The error likely comes from incorrectly resetting or managing tasks, not IOCP itself. You’re likely sending tasks with unsupported nQueryMode values (e.g., 21 or 0) that aren’t handled. somewhere, you are sending those values in to g_DbManager.m_hIOCPPut and then there's nothing to handle it, giving your error.


Memory Usage Insights​

The database server might sometimes use excessive RAM due to tasks piling up. For instance, saving a player involves allocating a new CMover on the heap, copying data, and posting it to the IOCP. If tasks aren’t handled efficiently, memory consumption increases. Here's an example of a potential memory-heavy scenario:

Ever wonder why the database server sometimes utilizes a lot of ram? While saving a player, the data that is sent over. A new CMover is allocated on heap, the data is copied in to and then that pointer is sent over as a task. These tasks can pile up and allocate way too much memory on heap. This is why constantly adding parameters to CMover affects the database to an extent and why there's rollback has to exist in most cases (good and bad).


You can see here there is an account cache system:
Hey There!
Please login and(or) register to see this awesome content today.

Hey There!
Please login and(or) register to see this awesome content today.


Here is save:
Hey There!
Please login and(or) register to see this awesome content today.

The connect to show the cache being used and intitialized with a new CMover as well:
Hey There!
Please login and(or) register to see this awesome content today.
(Note: I believe v21.2 source removes the CMover cache)
As you can see, memory can start increasing per player saving and why original servers had the delay set longer. Not only that, but most servers now force call save on every action rather than letting the Save timer do it -- which is good for certain actions obviously like trading, to prevent dupes with unexpected server crashes -- but also adds more usage on the DBServer.
 
Last edited:
Solution
Thank you for explaining. Another question. I have already have 16 gb of ram for the host. Is there a need to increase this? Or Can I just adjust the saving time for players? Upon checking the QUery numbers it is on the DB_Connect(0) and Update_guild_contribution(0). I got a debug also on CDPTrans::OnLogLevelup.(will follow up the Screenshot since I'm not on PC)

Edit: I also have the Record Book system. Which is saved every 15mins.

I've also got a debug pointed to OnLogLevelup
 

Attachments

  • IMG_20241006_162747.jpg
    IMG_20241006_162747.jpg
    46.4 KB · Views: 8
Last edited:
Thank you for explaining. Another question. I have already have 16 gb of ram for the host. Is there a need to increase this? Or Can I just adjust the saving time for players? Upon checking the QUery numbers it is on the DB_Connect(0) and Update_guild_contribution(0). I got a debug also on CDPTrans::OnLogLevelup.(will follow up the Screenshot since I'm not on PC)

Edit: I also have the Record Book system. Which is saved every 15mins.

I've also got a debug pointed to OnLogLevelup
I think you read without reading. Why would you debug OnLogLevelup. That was used as an example to explain what is going not the error.


Where are you sending that wrong data. Go find that. Clearly it's not the example I gave to explain the code. And if its messing with the IOCP put system it's possible you're not freeing the request when completed with the lpdoverlappedplus object, then that can cause it too.

Is it recordbook? Possible. Is it something else? Possible. Why you think I explained it in depth instead of saying "this is your issue".
 
Last edited:
Status
Not open for further replies.