Compare commits

...

2 Commits

Author SHA1 Message Date
Jacob Schmidt
39e7b2945a Merge branch 'master' of https://gitea.innovativedevsolutions.org/IDSolutions/ramdb
All checks were successful
Build / Build (push) Successful in 1m14s
2025-03-23 17:38:03 -05:00
Jacob Schmidt
2769a7cfd1 feat: Improve performance and stability
This commit includes several changes to improve the performance and stability of ArmaRAMDb:

*   **Increased Buffer Size:** Increased the buffer size in `Main.cs` to 10240 to handle larger data chunks.
*   **Debug Logging:** Added `#ifdef __A3__DEBUG__` preprocessor directives to enable debug logging in various `.sqf` functions for easier troubleshooting.
*   **Improved Chunking Logic:** Refactored the chunking logic in `Utils.cs` to correctly handle array data and improve efficiency.
*   **ListStore Formatting:** Modified `ListStore.cs` to correctly format list values as JSON strings when retrieving or setting list elements.
*   **Removed Unnecessary Code:** Removed unnecessary `_dataString` variable in `fnc_fetch.sqf`.
*   **Updated DLL/SO:** Updated the ArmaRAMDb_x64.dll and ArmaRAMDb_x64.so files.
2025-03-23 17:37:58 -05:00
32 changed files with 497 additions and 107 deletions

Binary file not shown.

Binary file not shown.

View File

@ -39,10 +39,15 @@ params [["_taskType", "", [""]], ["_key", "", [""]], ["_keyField", "", [""]], ["
private _task = [_taskType, _key, _keyField, _index, _value, _function, _call, _netId];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_addTask' Added Task '%1' to Queue", _task];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_addTask' Added Task '%1' to Queue", _task];
#endif
GVAR(taskQueue) pushBack _task;
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_addTask' Queue: %1", GVAR(taskQueue)];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_addTask' Queue Size: %1", count GVAR(taskQueue)];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_addTask' Queue: %1", GVAR(taskQueue)];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_addTask' Queue Size: %1", count GVAR(taskQueue)];
#endif
if !(GVAR(isProcessing)) then { [] spawn FUNC(processQueue); };

View File

@ -30,6 +30,12 @@
params [["_key", "", [""]]];
if (_key == "") exitWith { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_delete' Invalid Input for Key '%1'", _key]; };
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_delete' Key: '%1'", _key];
#endif
if (_key == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_delete' Invalid Input for Key '%1'", _key];
};
"ArmaRAMDb" callExtension ["del", [_key]];

View File

@ -20,11 +20,12 @@
["uniqueID", "function", "index", "indextotal", "datachunk", "call", "netId"]
*/
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_fetch' Input: %1", _this];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_fetch' Input: %1", _this];
#endif
params ["_uniqueID", "_function", "_index", "_total", "_datachunk", "_call", "_netId"];
private _dataString = "";
private _index_array = [];
private _count_total = -1;
@ -41,14 +42,36 @@ _count_total = {
if (_count_total == _total) then {
_index_array sort true;
for "_i" from 0 to (_total - 1) do {
_dataString = _dataString + ((_index_array select _i) select 1);
private _allElements = [];
{
private _chunkData = _x select 1;
private _chunkArray = [];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: Processing chunk: %1", _chunkData];
#endif
try {
_chunkArray = parseSimpleArray _chunkData;
_allElements append _chunkArray;
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: Parsed chunk successfully with %1 elements", count _chunkArray];
#endif
} catch {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: Error parsing chunk: %1", _chunkData];
#endif
};
} forEach _index_array;
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_fetch' DataString: %1", _dataString];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_fetch' Combined %1 chunks into array with %2 elements", count _index_array, count _allElements];
#endif
[_uniqueID, _function, _call, (parseSimpleArray _dataString), _netId] call FUNC(handler);
[_uniqueID, _function, _call, _allElements, _netId] call FUNC(handler);
// Cleanup
ramdb_db_fetch_array = ramdb_db_fetch_array select {!((_x select 0) in [_uniqueID])};
};

View File

@ -33,7 +33,9 @@
params [["_key", "", [""]], ["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_get' Key: '%1', Function: '%2', Call: '%3', NetId: '%4'", _key, _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_get' Key: '%1', Function: '%2', Call: '%3', NetId: '%4'", _key, _function, _call, _netId];
#endif
if (_key == "" || _function == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_get' Invalid Input for Key '%1' or Function '%2'", _key, _function];
@ -42,14 +44,20 @@ if (_key == "" || _function == "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_get' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["get", [_key, _function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["get", [_key, _function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_get' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["get", [_key, _function, _call]];
} else {
@ -57,5 +65,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_get' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_get' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -34,7 +34,9 @@
params [["_uniqueID", "", [""]], ["_function", "", [""]], ["_call", false, [false]], ["_data", [], [[]]], ["_netId", nil, [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_handler' UniqueID: '%1', Function: '%2', Call: '%3', Data: '%4', NetId: '%5'", _uniqueID, _function, _call, _data, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_handler' UniqueID: '%1', Function: '%2', Call: '%3', Data: '%4', NetId: '%5'", _uniqueID, _function, _call, _data, _netId];
#endif
if (_function == "" || count _data == 0) exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_handler' Invalid Input for Function '%1' or Data '%2'", _function, _data];

View File

@ -30,7 +30,9 @@
params [["_key", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashDeleteId' Key: '%1'", _key];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashDeleteId' Key: '%1'", _key];
#endif
if (_key == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashDeleteId' Invalid Input for Key '%1'", _key];

View File

@ -33,7 +33,9 @@
params [["_keyField", "", [""]], ["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGet' KeyField: '%1', Function: '%2', Call: '%3', NetId: '%4'", _keyField, _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGet' KeyField: '%1', Function: '%2', Call: '%3', NetId: '%4'", _keyField, _function, _call, _netId];
#endif
if (_keyField == "" || _function == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGet' Invalid Input for KeyField '%1' or Function '%2'", _keyField, _function];
@ -42,14 +44,20 @@ if (_keyField == "" || _function == "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGet' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hget", [_keyField, _function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["hget", [_keyField, _function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_hashGet' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hget", [_keyField, _function, _call]];
} else {
@ -57,5 +65,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGet' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGet' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -32,7 +32,9 @@
params [["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Function: '%1', Call: '%2', NetId: '%3'", _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Function: '%1', Call: '%2', NetId: '%3'", _function, _call, _netId];
#endif
if (_function isEqualTo "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Invalid Input for Function '%1'", _function];
@ -41,14 +43,20 @@ if (_function isEqualTo "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hgetall", [_function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["hgetall", [_function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hgetall", [_function, _call]];
} else {
@ -56,5 +64,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAll' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -33,7 +33,9 @@
params [["_key", "", [""]], ["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Key: '%1', Function: '%2', Call: '%3', NetId: '%4'", _key, _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Key: '%1', Function: '%2', Call: '%3', NetId: '%4'", _key, _function, _call, _netId];
#endif
if (_key == "" || _function == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Invalid Input for Key '%1' or Function '%2'", _key, _function];
@ -42,14 +44,20 @@ if (_key == "" || _function == "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hgetallid", [_key, _function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["hgetallid", [_key, _function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hgetallid", [_key, _function, _call]];
} else {
@ -57,5 +65,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetAllId' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -34,7 +34,9 @@
params [["_key", "", [""]], ["_keyField", "", [""]], ["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Key: '%1', KeyField: '%2', Function: '%3', Call: '%4', NetId: '%5'", _key, _keyField, _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Key: '%1', KeyField: '%2', Function: '%3', Call: '%4', NetId: '%5'", _key, _keyField, _function, _call, _netId];
#endif
if (_key == "" || _keyField == "" || _function == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Invalid Input for Key '%1', KeyField '%2' or Function '%3'", _key, _keyField, _function];
@ -43,14 +45,20 @@ if (_key == "" || _keyField == "" || _function == "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hgetid", [_key, _keyField, _function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["hgetid", [_key, _keyField, _function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["hgetid", [_key, _keyField, _function, _call]];
} else {
@ -58,5 +66,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashGetId' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -30,7 +30,9 @@
params [["_keyField", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashRemove' KeyField: '%1'", _keyField];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashRemove' KeyField: '%1'", _keyField];
#endif
if (_keyField == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashRemove' Invalid Input for KeyField '%1'", _keyField];

View File

@ -31,7 +31,9 @@
params [["_key", "", [""]], ["_keyField", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashRemoveId' Key: '%1', KeyField: '%2'", _key, _keyField];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashRemoveId' Key: '%1', KeyField: '%2'", _key, _keyField];
#endif
if (_key == "" || _keyField == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashRemoveId' Invalid Input for Key '%1' or KeyField '%2'", _key, _keyField];

View File

@ -31,7 +31,9 @@
params [["_keyField", "", [""]], ["_data", [], [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSet' KeyField: '%1', Data: '%2'", _keyField, _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSet' KeyField: '%1', Data: '%2'", _keyField, _data];
#endif
if (_keyField == "" || isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSet' Invalid Input for KeyField '%1' or Data '%2'", _keyField, _data];

View File

@ -30,7 +30,9 @@
params [["_data", [], [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetBulk' Data: %1", _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetBulk' Data: %1", _data];
#endif
if (isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetBulk' Invalid Input for Data '%1'", _data];

View File

@ -32,7 +32,9 @@
params [["_key", "", [""]], ["_keyField", "", [""]], ["_data", [], [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetId' Key: '%1', KeyField: '%2', Data: '%3'", _key, _keyField, _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetId' Key: '%1', KeyField: '%2', Data: '%3'", _key, _keyField, _data];
#endif
if (_key == "" || _keyField == "" || isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetId' Invalid Input for Key '%1', KeyField '%2' or Data '%3'", _key, _keyField, _data];

View File

@ -30,7 +30,9 @@
params [["_data", [], [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetIdBulk' Data: %1", _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetIdBulk' Data: %1", _data];
#endif
if (isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_hashSetIdBulk' Invalid Input for Data '%1'", _data];

View File

@ -31,7 +31,9 @@
params [["_key", "", [""]], ["_data", [], [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listAdd' Key: '%1', Data: '%2'", _key, _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listAdd' Key: '%1', Data: '%2'", _key, _data];
#endif
if (_key == "" || isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listAdd' Invalid Input for Key '%1' or Data '%2'", _key, _data];

View File

@ -30,7 +30,9 @@
params [["_key", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listDelete' Key: '%1'", _key];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listDelete' Key: '%1'", _key];
#endif
if (_key == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listDelete' Invalid Input for Key '%1'", _key];

View File

@ -34,7 +34,9 @@
params [["_key", "", [""]], ["_index", -1, [0]], ["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listGet' Key: '%1', Index: '%2', Function: '%3', Call: '%4', NetId: '%5'", _key, _index, _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listGet' Key: '%1', Index: '%2', Function: '%3', Call: '%4', NetId: '%5'", _key, _index, _function, _call, _netId];
#endif
if (_key == "" || _function == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listGet' Invalid Input for Key '%1' or Function '%2'", _key, _function];
@ -43,14 +45,20 @@ if (_key == "" || _function == "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listGet' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["listidx", [_key, _index, _function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["listidx", [_key, _index, _function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_listGet' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["listidx", [_key, _index, _function, _call]];
} else {
@ -58,5 +66,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listGet' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listGet' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -33,7 +33,9 @@
params [["_key", "", [""]], ["_function", "", [""]], ["_call", false, [false]], ["_netId", "", [""]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listLoad' Key: '%1', Function: '%2', Call: '%3', NetId: '%4'", _key, _function, _call, _netId];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listLoad' Key: '%1', Function: '%2', Call: '%3', NetId: '%4'", _key, _function, _call, _netId];
#endif
if (_key == "" || _function == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listLoad' Invalid Input for Key '%1' or Function '%2'", _key, _function];
@ -42,14 +44,20 @@ if (_key == "" || _function == "") exitWith {
private _return = "";
if (_netId != "") then {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listLoad' Using NetId: '%1'", _netId];
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["listrng", [_key, 0, -1, _function, _netId, _call]];
} else {
_return = "ArmaRAMDb" callExtension ["listrng", [_key, 0, -1, _function, _netId]];
};
} else {
#ifdef __A3__DEBUG__
diag_log text "ArmaRAMDb: 'ramdb_db_fnc_listLoad' Using current player";
#endif
if (_call) then {
_return = "ArmaRAMDb" callExtension ["listrng", [_key, 0, -1, _function, _call]];
} else {
@ -57,5 +65,8 @@ if (_netId != "") then {
};
};
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listLoad' Return: '%1'", _return];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listLoad' Return: '%1'", _return];
#endif
[(_return select 0)] call FUNC(scheduler);

View File

@ -31,7 +31,9 @@
params [["_key", "", [""]], ["_index", -1, [0]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listRemove' Key: '%1', Index: '%2'", _key, _index];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listRemove' Key: '%1', Index: '%2'", _key, _index];
#endif
if (_key == "") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listRemove' Invalid Input for Key '%1'", _key];

View File

@ -32,7 +32,9 @@
params [["_key", "", [""]], ["_index", -1, [0]], ["_data", [], [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listSet' Key: '%1', Index: '%2', Data: '%3'", _key, _index, _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listSet' Key: '%1', Index: '%2', Data: '%3'", _key, _index, _data];
#endif
if (_key == "" || isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_listSet' Invalid Input for Key '%1' or Data '%2'", _key, _data];

View File

@ -41,25 +41,123 @@ while { count GVAR(taskQueue) > 0} do {
private _call = _task select 6;
private _netId = _task select 7;
#ifdef __A3__DEBUG__
diag_log text format ["Initializing Task: %1", _task];
#endif
switch (_taskType) do {
case "get": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _function, _call, _netId] call FUNC(get); };
case "set": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _value] call FUNC(set); };
case "del": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key] call FUNC(delete); };
case "hget": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_keyField, _function, _call, _netId] call FUNC(hashGet); };
case "hgetid": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _keyField, _function, _call, _netId] call FUNC(hashGetId); };
case "hgetall": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_function, _call, _netId] call FUNC(hashGetAll); };
case "hgetallid": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _function, _call, _netId] call FUNC(hashGetAllId); };
case "hset": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_keyField, _value] call FUNC(hashSet); };
case "hsetbulk": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_value] call FUNC(hashSetBulk); };
case "hsetid": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _keyField, _value] call FUNC(hashSetId); };
case "hsetidbulk": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_value] call FUNC(hashSetIdBulk); };
case "listadd": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _value] call FUNC(listAdd); };
case "listidx": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _index, _function, _call, _netId] call FUNC(listGet); };
case "listrng": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _function, _call, _netId] call FUNC(listLoad); };
case "listrem": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _index] call FUNC(listRemove); };
case "listset": { diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType]; [_key, _index, _value] call FUNC(listSet); };
case "get": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _function, _call, _netId] call FUNC(get);
};
case "set": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _value] call FUNC(set);
};
case "del": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key] call FUNC(delete);
};
case "hget": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_keyField, _function, _call, _netId] call FUNC(hashGet);
};
case "hgetid": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _keyField, _function, _call, _netId] call FUNC(hashGetId);
};
case "hgetall": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_function, _call, _netId] call FUNC(hashGetAll);
};
case "hgetallid": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _function, _call, _netId] call FUNC(hashGetAllId);
};
case "hset": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_keyField, _value] call FUNC(hashSet);
};
case "hsetbulk": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_value] call FUNC(hashSetBulk);
};
case "hsetid": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _keyField, _value] call FUNC(hashSetId);
};
case "hsetidbulk": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_value] call FUNC(hashSetIdBulk);
};
case "listadd": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _value] call FUNC(listAdd);
};
case "listidx": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _index, _function, _call, _netId] call FUNC(listGet);
};
case "listrng": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _function, _call, _netId] call FUNC(listLoad);
};
case "listrem": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _index] call FUNC(listRemove);
};
case "listset": {
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_processQueue' Processing Task '%1'", _taskType];
#endif
[_key, _index, _value] call FUNC(listSet);
};
};
sleep 1;

View File

@ -28,6 +28,6 @@
* Public: Yes
*/
params [["_createBackup", false, [false]]];
params [["_createBackup", false, [false]]];
"ArmaRAMDb" callExtension ["save", []];

View File

@ -31,7 +31,9 @@
params [["_key", "", [""]], ["_data", "", [[]]]];
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_set' Key: '%1', Data: '%2'", _key, _data];
#ifdef __A3__DEBUG__
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_set' Key: '%1', Data: '%2'", _key, _data];
#endif
if (_key == "" || isNil "_data") exitWith {
diag_log text format ["ArmaRAMDb: 'ramdb_db_fnc_set' Invalid Input for Key '%1' or Data '%2'", _key, _data];

View File

@ -22,14 +22,8 @@ namespace ArmaRAMDb
lock (list)
{
if (value.StartsWith('[') && value.EndsWith(']'))
{
// Store the raw value without any formatting
list.Add(value);
}
else
{
list.Add($"[\"{value}\"]");
}
Main.Log($"ListAdd: {listName} - Value: {value}", "debug");
}
}
@ -53,6 +47,13 @@ namespace ArmaRAMDb
{
int idx = int.Parse(index);
string value = idx >= 0 && idx < list.Count ? list[idx] : string.Empty;
// Format the value if it's not already formatted as an array
if (!string.IsNullOrEmpty(value) && !(value.StartsWith('[') && value.EndsWith(']')))
{
value = $"[\"{value.Replace("\"", "\\\"")}\"]";
}
Main.Log($"ListIndex: {listName} - Index: {idx} - Value: {value}", "debug");
Utils.CheckByteCount(uniqueId, value, function, entity, Convert.ToBoolean(call), bufferSize);
}
@ -80,7 +81,11 @@ namespace ArmaRAMDb
{
int count = end - start + 1;
var value = list.GetRange(start, count);
string data = string.Join(",", value);
// Format each item as a JSON string if it's not already
var formattedItems = value.Select(item => (item.StartsWith('[') && item.EndsWith(']')) ? item : $"[\"{item.Replace("\"", "\\\"")}\"]");
string data = string.Join(",", formattedItems);
Main.Log($"ListRange: {listName} - StartIndex: {start} - EndIndex: {end} - Count: {count}", "debug");
Utils.CheckByteCount(uniqueId, $"[{data}]", function, entity, Convert.ToBoolean(call), bufferSize);
}
@ -109,14 +114,8 @@ namespace ArmaRAMDb
int idx = int.Parse(index);
if (idx >= 0 && idx < list.Count)
{
if (value.StartsWith('[') && value.EndsWith(']'))
{
// Store the value as-is, just like ListAddAsync
list[idx] = value;
}
else
{
list[idx] = $"[\"{value}\"]";
}
Main.Log($"ListSet: {listName} - Index: {idx} - Value: {value}", "debug");
}
}

View File

@ -18,7 +18,7 @@ namespace ArmaRAMDb
public class Main
{
private const string ARDB_VERSION = "1.0.0";
public const int ARDB_BUFFERSIZE = 1024;
public const int ARDB_BUFFERSIZE = 10240;
public static readonly string DEFAULT_ARDB_PATH = $"@ramdb{Path.DirectorySeparatorChar}ArmaRAMDb.ardb";
public static string ARDB_LOGFOLDER { get; private set; } = $"{Path.DirectorySeparatorChar}@ramdb{Path.DirectorySeparatorChar}logs";
public static bool ARDB_DEBUG {get; private set; } = false;

View File

@ -24,16 +24,76 @@ namespace ArmaRAMDb
return str;
}
public static List<string> SplitIntoChunks(string data, int chunkSize)
public static List<string> SplitIntoChunks(string data, int maxChunkSize)
{
int chunksNeeded = (int)Math.Ceiling((double)data.Length / chunkSize);
List<string> chunks = [];
for (int i = 0; i < chunksNeeded; i++)
if (data.StartsWith("[") && data.EndsWith("]"))
{
int start = i * chunkSize;
int end = Math.Min(data.Length, start + chunkSize);
chunks.Add(data[start..end]);
string innerData = data[1..^1];
List<string> elements = [];
int depth = 0;
int startPos = 0;
for (int i = 0; i < innerData.Length; i++)
{
char c = innerData[i];
if (c == '[') depth++;
else if (c == ']') depth--;
else if (c == ',' && depth == 0)
{
elements.Add(innerData[startPos..i]);
startPos = i + 1;
}
}
if (startPos < innerData.Length)
{
elements.Add(innerData[startPos..]);
}
StringBuilder currentChunk = new StringBuilder();
foreach (string element in elements)
{
if (currentChunk.Length > 0 &&
Encoding.UTF8.GetByteCount(currentChunk.ToString() + "," + element) > maxChunkSize)
{
chunks.Add(currentChunk.ToString());
currentChunk.Clear();
}
if (currentChunk.Length > 0)
{
currentChunk.Append(",");
}
currentChunk.Append(element);
}
if (currentChunk.Length > 0)
{
chunks.Add(currentChunk.ToString());
}
}
else
{
int bytesProcessed = 0;
while (bytesProcessed < Encoding.UTF8.GetByteCount(data))
{
int charCount = 0;
while (bytesProcessed + Encoding.UTF8.GetByteCount(data.Substring(bytesProcessed, Math.Min(charCount + 1, data.Length - bytesProcessed))) <= maxChunkSize &&
bytesProcessed + charCount < data.Length)
{
charCount++;
}
chunks.Add(data.Substring(bytesProcessed, charCount));
bytesProcessed += charCount;
}
}
return chunks;
@ -45,26 +105,122 @@ namespace ArmaRAMDb
{
if (!data.StartsWith('['))
data = BuildArray(data);
Main.Log($"{data}", "debug");
Main.Log($"Single chunk data: {data}", "debug");
string dataAsString = $"[\"{uniqueId}\",\"{function}\",{call},{data},\"{entity}\"]";
Main.Log($"{dataAsString}", "debug");
string dataAsString = $"[\"{uniqueId}\",\"{function}\",{call.ToString().ToLower()},{data},\"{entity}\"]";
Main.Callback("ArmaRAMDb", "ramdb_db_fnc_handler", dataAsString);
}
else
{
if (!data.StartsWith('['))
data = BuildArray(data);
Main.Log($"{data}", "debug");
var chunks = SplitIntoChunks(data, bufferSize);
int totalChunks = chunks.Count;
foreach (string chunk in chunks)
if (!data.StartsWith('[') || !data.EndsWith(']'))
{
string chunkAsString = $"[{uniqueId},{function},{chunks.IndexOf(chunk)},{totalChunks},\"{chunk}\",{call},\"{entity}\"]";
data = BuildArray(data);
}
List<string> elements = ParseArrayElements(data);
int totalChunks = CalculateChunks(elements, bufferSize);
for (int chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++)
{
List<string> chunkElements = GetChunkElements(elements, chunkIndex, totalChunks);
string chunkData = "[" + string.Join(",", chunkElements) + "]";
string escapedChunkData = chunkData.Replace("\"", "\"\"");
string chunkAsString = $"[\"{uniqueId}\",\"{function}\",{chunkIndex+1},{totalChunks},\"{escapedChunkData}\",{call.ToString().ToLower()},\"{entity}\"]";
Main.Log($"Sending chunk {chunkIndex+1}/{totalChunks}: {chunkAsString}", "debug");
Main.Callback("ArmaRAMDb", "ramdb_db_fnc_fetch", chunkAsString);
}
}
}
private static List<string> ParseArrayElements(string arrayString)
{
List<string> elements = [];
string content = arrayString[1..^1].Trim();
if (string.IsNullOrEmpty(content))
return elements;
int startPos = 0;
int nestLevel = 0;
bool inQuotes = false;
for (int i = 0; i < content.Length; i++)
{
char c = content[i];
if (c == '\\' && i + 1 < content.Length && content[i + 1] == '"')
{
i++;
continue;
}
if (c == '"')
inQuotes = !inQuotes;
if (!inQuotes)
{
if (c == '[') nestLevel++;
else if (c == ']') nestLevel--;
if (nestLevel == 0 && c == ',')
{
elements.Add(content[startPos..i].Trim());
startPos = i + 1;
}
}
}
if (startPos < content.Length)
{
elements.Add(content[startPos..].Trim());
}
return elements;
}
private static int CalculateChunks(List<string> elements, int bufferSize)
{
int chunks = 1;
int currentSize = 2;
foreach (string element in elements)
{
int elementSize = Encoding.UTF8.GetByteCount(element) + 1;
if (currentSize + elementSize > bufferSize)
{
chunks++;
currentSize = 2 + elementSize;
}
else
{
currentSize += elementSize;
}
}
return chunks;
}
private static List<string> GetChunkElements(List<string> allElements, int chunkIndex, int totalChunks)
{
int elementsPerChunk = (int)Math.Ceiling((double)allElements.Count / totalChunks);
int startIdx = chunkIndex * elementsPerChunk;
int count = Math.Min(elementsPerChunk, allElements.Count - startIdx);
List<string> result = [];
for (int i = 0; i < count; i++)
{
if (startIdx + i < allElements.Count)
result.Add(allElements[startIdx + i]);
}
return result;
}
}
}