From 9d792ef2a7b24172d04a85797c97f9f241cde17f Mon Sep 17 00:00:00 2001 From: nwrl Date: Thu, 7 Aug 2025 14:52:14 -0500 Subject: Add database locking where necessary --- nameblocker.sp | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'nameblocker.sp') diff --git a/nameblocker.sp b/nameblocker.sp index 9e16b97..c4c945c 100644 --- a/nameblocker.sp +++ b/nameblocker.sp @@ -32,6 +32,8 @@ // first writing to the database and then updating the lists, there realistically shouldn't be any weird memory problems. // That makes this a whole lot easier + // If database locking takes too long I might need to use threaded calls, which sounds like a fucking nightmare + #pragma newdecls required #pragma semicolon 1 @@ -124,39 +126,60 @@ void xRegisterIntConVar(ConVar& cv, int defaultVal, const char[] name, const cha int initPrepStatements() { char sqlerr[256 + 1]; - if((dbInsert = SQL_PrepareQuery(db, DBINSERTSTATEMENT, sqlerr, sizeof(sqlerr))) == null) + SQL_LockDatabase(db); + if((dbInsert = SQL_PrepareQuery(db, DBINSERTSTATEMENT, sqlerr, sizeof(sqlerr))) == null) { logAndFail("Could not prepare insert statement: %s", sqlerr); - if((dbDelete = SQL_PrepareQuery(db, DBDELETESTATEMENT, sqlerr, sizeof(sqlerr))) == null) + SQL_UnlockDatabase(db); + } + if((dbDelete = SQL_PrepareQuery(db, DBDELETESTATEMENT, sqlerr, sizeof(sqlerr))) == null) { logAndFail("Could not prepare delete statement: %s", sqlerr); - if((dbReplace = SQL_PrepareQuery(db, DBREPLACESTATEMENT, sqlerr, sizeof(sqlerr))) == null) + SQL_UnlockDatabase(db); + } + if((dbReplace = SQL_PrepareQuery(db, DBREPLACESTATEMENT, sqlerr, sizeof(sqlerr))) == null) { logAndFail("Could not prepare replace statement: %s", sqlerr); - if((dbPopulate = SQL_PrepareQuery(db, DBPOPULATESTATEMENT, sqlerr, sizeof(sqlerr))) == null) + SQL_UnlockDatabase(db); + } + if((dbPopulate = SQL_PrepareQuery(db, DBPOPULATESTATEMENT, sqlerr, sizeof(sqlerr))) == null) { logAndFail("Could not prepare populate statement: %s", sqlerr); + SQL_UnlockDatabase(db); + } // This might not work / I might have to use Format() instead of binding. We will see if(SQL_BindParamString(dbInsert, 0, DBTABLENAME, true)) { SQL_GetError(dbInsert, sqlerr, sizeof(sqlerr)); + SQL_UnlockDatabase(db); logAndFail("Could not bind tablename to insert statement: %s", sqlerr); } if(SQL_BindParamString(dbDelete, 0, DBTABLENAME, true)) { SQL_GetError(dbDelete, sqlerr, sizeof(sqlerr)); + SQL_UnlockDatabase(db); logAndFail("Could not bind tablename to delete statement: %s", sqlerr); } if( SQL_BindParamString(dbReplace, 0, DBTABLENAME, true)) { SQL_GetError(dbReplace, sqlerr, sizeof(sqlerr)); + SQL_UnlockDatabase(db); logAndFail("Could not bind tablename to replace statement: %s", sqlerr); } if(SQL_BindParamString(dbPopulate, 0, DBTABLENAME, true)) { SQL_GetError(dbPopulate, sqlerr, sizeof(sqlerr)); + SQL_UnlockDatabase(db); logAndFail("Could not bind tablename to populate statement: %s", sqlerr); } // If I knew how to do macros this would be much nicer + SQL_UnlockDatabase(db); return 0; } int loadFromDatabase() { + // Initialize and populate datatypes + regexlist = new ArrayList(ByteCountToCells(HANDLE_SIZE)); + if(regexlist == null) logAndFail("Could not initialize regexlist ArrayList"); + + patternlist = new ArrayList(ByteCountToCells(PATTERN_MAX_LEN)); + if(patternlist == null) logAndFail("Could not initialize patternlist ArrayList"); + // Get database handle char sqlerr[256 + 1]; db = SQLite_UseDatabase("sourcemod-local", sqlerr, sizeof(sqlerr)); @@ -166,23 +189,21 @@ int loadFromDatabase() { // I could make this a prepared statement, but I don't believe it's entirely necessary char sqlcbuf[256 + 1]; Format(sqlcbuf, sizeof(sqlcbuf), "CREATE TABLE IF NOT EXISTS \"%s\" (id INTEGER NOT NULL, regexstr TEXT NOT NULL ON CONFLICT IGNORE, steamid64 TEXT NOT NULL ON CONFLICT IGNORE, dateof TEXT DEFAULT CURRENT_DATE, timeof TEXT DEFAULT CURRENT_TIME, PRIMARY KEY (id), UNIQUE (regexstr));", DBTABLENAME); + + SQL_LockDatabase(db); if(!SQL_FastQuery(db, sqlcbuf)) { SQL_GetError(db, sqlerr, sizeof(sqlerr)); + SQL_UnlockDatabase(db); logAndFail("Could not initialize nameblocker table: %s", sqlerr); } - // Initialize and populate datatypes - regexlist = new ArrayList(ByteCountToCells(HANDLE_SIZE)); - if(regexlist == null) logAndFail("Could not initialize regexlist ArrayList"); - - patternlist = new ArrayList(ByteCountToCells(PATTERN_MAX_LEN)); - if(patternlist == null) logAndFail("Could not initialize patternlist ArrayList"); - // select patterns from nameblock table/database if(SQL_Execute(dbPopulate)) { SQL_GetError(dbPopulate, sqlerr, sizeof(sqlerr)); + SQL_UnlockDatabase(db); logAndFail("Population query failed"); } + SQL_UnlockDatabase(db); // compile each pattern & insert Regex cur; char reerr[256]; RegexError reenum; -- cgit v1.2.3