SQLiteServerLoggerPlugin.cpp 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. #include "SQLiteServerLoggerPlugin.h"
  2. #include "RakPeerInterface.h"
  3. #include "PacketizedTCP.h"
  4. #include "MessageIdentifiers.h"
  5. #include "SQLiteLoggerCommon.h"
  6. #include "jpeglib.h"
  7. #include "jpeg_memory_dest.h"
  8. #include "FileOperations.h"
  9. #include "GetTime.h"
  10. #include <time.h>
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #include <sys/timeb.h>
  14. #include "DXTCompressor.h"
  15. // http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
  16. // See jmorecfg.h
  17. /*
  18. * Ordering of RGB data in scanlines passed to or from the application.
  19. * If your application wants to deal with data in the order B,G,R, just
  20. * change these macros. You can also deal with formats such as R,G,B,X
  21. * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
  22. * the offsets will also change the order in which colormap data is organized.
  23. * RESTRICTIONS:
  24. * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
  25. * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
  26. * useful if you are using JPEG color spaces other than YCbCr or grayscale.
  27. * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
  28. * is not 3 (they don't understand about dummy color components!). So you
  29. * can't use color quantization if you change that value.
  30. */
  31. //#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
  32. //#define RGB_GREEN 1 /* Offset of Green */
  33. //#define RGB_BLUE 2 /* Offset of Blue */
  34. //#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
  35. using namespace RakNet;
  36. // JPEG ENCODING ERRORS
  37. struct my_error_mgr {
  38. struct jpeg_error_mgr pub;
  39. };
  40. METHODDEF(void) my_error_exit (j_common_ptr cinfo) {}
  41. #define FILE_COLUMN "SourceFile"
  42. #define LINE_COLUMN "SourceLine"
  43. #define TICK_COUNT_COLUMN "AutoTickCount"
  44. #define AUTO_IP_COLUMN "AutoIPAddress"
  45. #define TIMESTAMP_NUMERIC_COLUMN "TimestampNumeric"
  46. #define TIMESTAMP_TEXT_COLUMN "TimestampText"
  47. #define FUNCTION_CALL_FRIENDLY_TEXT "FunctionCallFriendlyText"
  48. #define FUNCTION_CALL_TABLE "'functionCalls'"
  49. #define FUNCTION_CALL_PARAMETERS_TABLE "'functionCallParameters'"
  50. // Store packets in the CPUThreadInput until at most this much time has elapsed. This is so
  51. // batch processing can occur on multiple image sources at once
  52. static const RakNet::TimeMS MAX_TIME_TO_BUFFER_PACKETS=1000;
  53. // WTF am I getting this?
  54. // 2>SQLiteServerLoggerPlugin.obj : error LNK2019: unresolved external symbol _GetSqlDataTypeName referenced in function "struct RakNet::SQLite3ServerPlugin::SQLExecThreadOutput __cdecl ExecSQLLoggingThread(struct RakNet::SQLite3ServerPlugin::SQLExecThreadInput,bool *,void *)" (?ExecSQLLoggingThread@@YA?AUExecThreadOutput@SQLite3ServerPlugin@RakNet@@UExecThreadInput@23@PA_NPAX@Z)
  55. // 2>C:\RakNet\Debug\SQLiteServerLogger.exe : fatal error LNK1120: 1 unresolved externals
  56. static const char *sqlDataTypeNames[SQLLPDT_COUNT] =
  57. {
  58. "INTEGER",
  59. "INTEGER",
  60. "NUMERIC",
  61. "TEXT",
  62. "BLOB",
  63. "BLOB",
  64. };
  65. const char *GetSqlDataTypeName2(SQLLoggerPrimaryDataType idx) {return sqlDataTypeNames[(int)idx];}
  66. void CompressAsJpeg(char **cptrInOut, uint32_t *sizeInOut, uint16_t imageWidth, uint16_t imageHeight, int16_t linePitch, unsigned char input_components)
  67. {
  68. RakNet::TimeUS t1=RakNet::GetTimeUS();
  69. // Compress to jpg
  70. // http://www.google.com/codesearch/p?hl=en#I-_InJ6STRE/gthumb-1.108/libgthumb/pixbuf-utils.c&q=jpeg_create_compress
  71. // http://ftp.gnome.org / pub/ GNOME / sources /gthumb /1.108/ gthumb-1.108.tar.gz/
  72. struct jpeg_compress_struct cinfo;
  73. struct my_error_mgr jerr;
  74. cinfo.err = jpeg_std_error(&jerr.pub);
  75. jerr.pub.error_exit = my_error_exit;
  76. jpeg_create_compress(&cinfo);
  77. cinfo.smoothing_factor = 0;
  78. cinfo.optimize_coding = false;
  79. cinfo.image_width = imageWidth;
  80. cinfo.image_height = imageHeight;
  81. cinfo.input_components = input_components;
  82. cinfo.in_color_space = JCS_RGB;
  83. jpeg_set_defaults (&cinfo);
  84. cinfo.dct_method=JDCT_FLOAT;
  85. // Not sure why they made RGB_PIXELSIZE a global define. I added this so it only uses my value in this one place, to not break other things
  86. cinfo.hack_use_input_components_as_RGB_PIXELSIZE=1;
  87. jpeg_set_quality (&cinfo, 75, TRUE);
  88. int jpegSizeAfterCompression = 0; //size of jpeg after compression
  89. char * storage = (char*) rakMalloc_Ex(*sizeInOut+50000,_FILE_AND_LINE_);
  90. jpeg_memory_dest(&cinfo,(JOCTET*)storage,*sizeInOut+50000,&jpegSizeAfterCompression);
  91. JSAMPROW row_pointer[1];
  92. jpeg_start_compress (&cinfo, TRUE);
  93. while( cinfo.next_scanline < cinfo.image_height )
  94. {
  95. row_pointer[0] = (JSAMPROW) &((*cptrInOut)[cinfo.next_scanline * linePitch ]);
  96. jpeg_write_scanlines(&cinfo, row_pointer, 1);
  97. }
  98. /* finish off */
  99. jpeg_finish_compress (&cinfo);
  100. jpeg_destroy_compress(&cinfo);
  101. rakFree_Ex(*cptrInOut,_FILE_AND_LINE_);
  102. *cptrInOut = (char*) rakRealloc_Ex(storage, jpegSizeAfterCompression,_FILE_AND_LINE_);
  103. *sizeInOut=jpegSizeAfterCompression;
  104. RakNet::TimeUS t2=RakNet::GetTimeUS();
  105. RakNet::TimeUS diff=t2-t1;
  106. }
  107. static bool needsDxtInit=true;
  108. static bool dxtCompressionSupported=false;
  109. void* InitDxt()
  110. {
  111. if (needsDxtInit==true)
  112. {
  113. dxtCompressionSupported=DXTCompressor::Initialize();
  114. if (dxtCompressionSupported==false)
  115. {
  116. printf("Warning, DXT compressor failed to start.\nImages will be compressed with jpg instead.\n");
  117. }
  118. }
  119. needsDxtInit=false;
  120. return 0;
  121. }
  122. void DeinitDxt(void*)
  123. {
  124. if (dxtCompressionSupported)
  125. DXTCompressor::Shutdown();
  126. needsDxtInit=true;
  127. dxtCompressionSupported=false;
  128. }
  129. SQLiteServerLoggerPlugin::CPUThreadOutput* ExecCPULoggingThread(SQLiteServerLoggerPlugin::CPUThreadInput* cpuThreadInput, bool *returnOutput, void* perThreadData)
  130. {
  131. int i;
  132. *returnOutput=true;
  133. SQLiteServerLoggerPlugin::CPUThreadOutput *cpuThreadOutput = RakNet::OP_NEW<SQLiteServerLoggerPlugin::CPUThreadOutput>(_FILE_AND_LINE_);
  134. cpuThreadOutput->arraySize=cpuThreadInput->arraySize;
  135. //cpuThreadOutput->cpuOutputNodeArray=RakNet::OP_NEW_ARRAY<SQLiteServerLoggerPlugin::CPUThreadOutputNode*>(cpuThreadInput->arraySize,_FILE_AND_LINE_);
  136. //printf("1. arraySize=%i, ",cpuThreadInput->arraySize);
  137. for (i=0; i<cpuThreadInput->arraySize; i++)
  138. {
  139. cpuThreadOutput->cpuOutputNodeArray[i]=RakNet::OP_NEW<SQLiteServerLoggerPlugin::CPUThreadOutputNode>(_FILE_AND_LINE_);
  140. SQLiteServerLoggerPlugin::CPUThreadOutputNode *outputNode = cpuThreadOutput->cpuOutputNodeArray[i];
  141. Packet *packet = cpuThreadInput->cpuInputArray[i].packet;
  142. RakNet::RakString dbIdentifier = cpuThreadInput->cpuInputArray[i].dbIdentifier;
  143. // outputNode->whenMessageArrived = cpuThreadInput->cpuInputArray[i].whenMessageArrived;
  144. outputNode->packet=packet;
  145. packet->systemAddress.ToString(true,outputNode->ipAddressString);
  146. RakNet::BitStream bitStream(packet->data, packet->length, false);
  147. bitStream.IgnoreBytes(1);
  148. bitStream.Read(outputNode->dbIdentifier);
  149. bitStream.Read(outputNode->tableName);
  150. outputNode->tableName.SQLEscape();
  151. bitStream.Read(outputNode->line);
  152. bitStream.Read(outputNode->file);
  153. bitStream.Read(outputNode->tickCount);
  154. bitStream.Read(outputNode->clientSendingTime);
  155. bitStream.Read(outputNode->isFunctionCall);
  156. bitStream.Read(outputNode->parameterCount);
  157. if (outputNode->isFunctionCall==false)
  158. {
  159. RakNet::RakString columnName;
  160. // printf("2. parameterCount=%i, ",outputNode->parameterCount);
  161. for (int i=0; i < outputNode->parameterCount; i++)
  162. {
  163. bitStream.Read(columnName);
  164. columnName.SQLEscape();
  165. columnName.RemoveCharacter(' ');
  166. outputNode->insertingColumnNames.Push(columnName, _FILE_AND_LINE_ );
  167. }
  168. }
  169. int parameterCountIndex=0;
  170. // printf("3. parameterCount=%i, ",outputNode->parameterCount);
  171. while (parameterCountIndex < outputNode->parameterCount)
  172. {
  173. outputNode->parameterList[parameterCountIndex].Deserialize(&bitStream);
  174. if (outputNode->parameterList[parameterCountIndex].size>0)
  175. {
  176. parameterCountIndex++;
  177. }
  178. else
  179. {
  180. // Skip empty parameters
  181. if (outputNode->isFunctionCall==false)
  182. outputNode->insertingColumnNames.RemoveAtIndex(parameterCountIndex);
  183. outputNode->parameterCount--;
  184. }
  185. }
  186. // sqlite3_stmt *statement;
  187. // char *errorMsg;
  188. // printf("4. parameterCount=%i, ",outputNode->parameterCount);
  189. for (parameterCountIndex=0; parameterCountIndex < outputNode->parameterCount; parameterCountIndex++)
  190. {
  191. if (outputNode->parameterList[parameterCountIndex].type==SQLLPDT_IMAGE)
  192. {
  193. bool dxtCompressSuccess=false;
  194. if (dxtCompressionSupported)
  195. {
  196. char *outputData;
  197. int bufferSize = DXTCompressor::GetBufferSize(DXT1,
  198. outputNode->parameterList[parameterCountIndex].imageWidth,
  199. outputNode->parameterList[parameterCountIndex].imageHeight);
  200. int ddsHeaderSize = DXTCompressor::GetDDSHeaderSize();
  201. outputData = (char*) rakMalloc_Ex(bufferSize + ddsHeaderSize, _FILE_AND_LINE_ );
  202. dxtCompressSuccess = DXTCompressor::CompressImageData(
  203. DXT1,
  204. outputNode->parameterList[parameterCountIndex].data.cptr,
  205. outputNode->parameterList[parameterCountIndex].imageWidth,
  206. outputNode->parameterList[parameterCountIndex].imageHeight,
  207. outputData+ddsHeaderSize, false, outputNode->parameterList[parameterCountIndex].sourceFormatIsBGRA );
  208. if (dxtCompressSuccess)
  209. {
  210. rakFree_Ex(outputNode->parameterList[parameterCountIndex].data.cptr,_FILE_AND_LINE_);
  211. DXTCompressor::WriteDDSHeader(DXT1,
  212. outputNode->parameterList[parameterCountIndex].imageWidth,
  213. outputNode->parameterList[parameterCountIndex].imageHeight,
  214. bufferSize,
  215. outputData);
  216. outputNode->parameterList[parameterCountIndex].data.cptr=outputData;
  217. outputNode->parameterList[parameterCountIndex].size=bufferSize + ddsHeaderSize;
  218. // static bool testWriteToDisk=true;
  219. // if (testWriteToDisk)
  220. // {
  221. // printf("Wrote test.dds\n");
  222. // FILE *fp = fopen("test.dds", "wb");
  223. // fwrite(outputData,1,outputNode->parameterList[parameterCountIndex].size,fp);
  224. // fclose(fp);
  225. // testWriteToDisk=false;
  226. // }
  227. }
  228. else
  229. {
  230. rakFree_Ex(outputData,_FILE_AND_LINE_);
  231. }
  232. }
  233. if (dxtCompressSuccess==false)
  234. {
  235. if (outputNode->parameterList[parameterCountIndex].sourceFormatIsBGRA)
  236. {
  237. // Endian swap each color component. Input should be RGBA
  238. // int pixelIndex;
  239. // int rowIndex;
  240. int imageHeight = outputNode->parameterList[parameterCountIndex].imageHeight;
  241. // int imageWidth = outputNode->parameterList[parameterCountIndex].imageWidth;
  242. int bytesPerPixel = outputNode->parameterList[parameterCountIndex].input_components;
  243. int linePitch = outputNode->parameterList[parameterCountIndex].linePitch;
  244. char *dataPtr = outputNode->parameterList[parameterCountIndex].data.cptr;
  245. int totalBytes=linePitch*imageHeight;
  246. char *endPtr = dataPtr+totalBytes;
  247. unsigned char temp1;
  248. if (bytesPerPixel==3)
  249. {
  250. while (dataPtr!=endPtr)
  251. {
  252. temp1=dataPtr[2];
  253. dataPtr[2]=dataPtr[0];
  254. dataPtr[0]=temp1;
  255. dataPtr+=3;
  256. }
  257. }
  258. else
  259. {
  260. RakAssert(bytesPerPixel==4);
  261. while (dataPtr!=endPtr)
  262. {
  263. temp1=dataPtr[2];
  264. dataPtr[2]=dataPtr[0];
  265. dataPtr[0]=temp1;
  266. dataPtr+=4;
  267. }
  268. }
  269. }
  270. CompressAsJpeg(
  271. &outputNode->parameterList[parameterCountIndex].data.cptr,
  272. &outputNode->parameterList[parameterCountIndex].size,
  273. outputNode->parameterList[parameterCountIndex].imageWidth,
  274. outputNode->parameterList[parameterCountIndex].imageHeight,
  275. outputNode->parameterList[parameterCountIndex].linePitch,
  276. outputNode->parameterList[parameterCountIndex].input_components
  277. );
  278. //
  279. // static bool testWriteToDisk=true;
  280. // if (testWriteToDisk)
  281. // {
  282. // printf("Wrote test.jpg\n");
  283. // FILE *fp = fopen("test.jpg", "wb");
  284. // fwrite(outputNode->parameterList[parameterCountIndex].data.cptr,1,outputNode->parameterList[parameterCountIndex].size,fp);
  285. // fclose(fp);
  286. // testWriteToDisk=false;
  287. // }
  288. }
  289. }
  290. }
  291. }
  292. // printf("5. out1, ");
  293. RakNet::OP_DELETE(cpuThreadInput,_FILE_AND_LINE_);
  294. // printf("6. out2\n");
  295. return cpuThreadOutput;
  296. }
  297. struct SQLPreparedStatements
  298. {
  299. SQLPreparedStatements()
  300. {
  301. selectNameFromMaster=0;
  302. insertIntoFunctionCalls=0;
  303. insertIntoFunctionCallParameters=0;
  304. }
  305. sqlite3_stmt *selectNameFromMaster;
  306. sqlite3_stmt *insertIntoFunctionCalls;
  307. sqlite3_stmt *insertIntoFunctionCallParameters;
  308. };
  309. void* SQLLoggerThreadAllocPreparedStatements()
  310. {
  311. SQLPreparedStatements *s = RakNet::OP_NEW<SQLPreparedStatements>(_FILE_AND_LINE_);
  312. return s;
  313. }
  314. void SQLLoggerThreadDeallocPreparedStatements(void* statementStruct)
  315. {
  316. SQLPreparedStatements *s = (SQLPreparedStatements *) statementStruct;
  317. if (s->selectNameFromMaster) sqlite3_finalize(s->selectNameFromMaster);
  318. if (s->insertIntoFunctionCalls) sqlite3_finalize(s->insertIntoFunctionCalls);
  319. if (s->insertIntoFunctionCallParameters) sqlite3_finalize(s->insertIntoFunctionCallParameters);
  320. RakNet::OP_DELETE(s,_FILE_AND_LINE_);
  321. }
  322. void DeleteBlobOrText(void* v)
  323. {
  324. LogParameter::Free(v);
  325. }
  326. SQLiteServerLoggerPlugin::SQLThreadOutput ExecSQLLoggingThread(SQLiteServerLoggerPlugin::SQLThreadInput sqlThreadInput, bool *returnOutput, void* perThreadData)
  327. {
  328. SQLiteServerLoggerPlugin::CPUThreadOutputNode *cpuOutputNode = sqlThreadInput.cpuOutputNode;
  329. SQLPreparedStatements *preparedStatements = (SQLPreparedStatements*) perThreadData;
  330. *returnOutput=true;
  331. SQLiteServerLoggerPlugin::SQLThreadOutput sqlThreadOutput;
  332. sqlThreadOutput.cpuOutputNode=cpuOutputNode;
  333. sqlite3 *dbHandle = sqlThreadInput.dbHandle;
  334. // sqlite3_stmt *statement;
  335. char *errorMsg;
  336. sqlite3_exec(dbHandle,"BEGIN TRANSACTION", 0, 0, 0);
  337. int rc;
  338. if (cpuOutputNode->isFunctionCall)
  339. {
  340. if (preparedStatements->selectNameFromMaster==0)
  341. {
  342. // Create function tables if they are not there already
  343. if (sqlite3_prepare_v2(
  344. dbHandle,
  345. "SELECT name FROM sqlite_master WHERE type='table' AND name="FUNCTION_CALL_TABLE" ",
  346. -1,
  347. &preparedStatements->selectNameFromMaster,
  348. 0
  349. )!=SQLITE_OK)
  350. {
  351. RakAssert("Failed PRAGMA table_info for function tables in SQLiteServerLoggerPlugin.cpp" && 0);
  352. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  353. cpuOutputNode->parameterList[i].Free();
  354. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  355. return sqlThreadOutput;
  356. }
  357. }
  358. rc = sqlite3_step(preparedStatements->selectNameFromMaster);
  359. sqlite3_reset(preparedStatements->selectNameFromMaster);
  360. if (rc!=SQLITE_ROW)
  361. {
  362. // Create table if it isn't there already
  363. rc = sqlite3_exec(dbHandle,"CREATE TABLE "FUNCTION_CALL_TABLE" (functionId_pk INTEGER PRIMARY KEY, "FUNCTION_CALL_FRIENDLY_TEXT" TEXT, functionName TEXT, "FILE_COLUMN" TEXT, "LINE_COLUMN" INTEGER, "TICK_COUNT_COLUMN" INTEGER, "AUTO_IP_COLUMN" TEXT, "TIMESTAMP_TEXT_COLUMN" TIMESTAMP DATE DEFAULT (datetime('now','localtime')), "TIMESTAMP_NUMERIC_COLUMN" NUMERIC )", 0, 0, &errorMsg);
  364. RakAssert(rc==SQLITE_OK);
  365. sqlite3_free(errorMsg);
  366. // See sqlDataTypeNames for *val
  367. rc = sqlite3_exec(dbHandle,"CREATE TABLE "FUNCTION_CALL_PARAMETERS_TABLE" (fcpId_pk INTEGER PRIMARY KEY, functionId_fk integer NOT NULL, value TEXT, FOREIGN KEY (functionId_fk) REFERENCES "FUNCTION_CALL_TABLE" (functionId_pk))", 0, 0, &errorMsg);
  368. RakAssert(rc==SQLITE_OK);
  369. sqlite3_free(errorMsg);
  370. }
  371. else
  372. {
  373. // Table already there
  374. }
  375. // Insert into function calls
  376. int parameterCountIndex;
  377. RakNet::RakString functionCallFriendlyText("%s(", cpuOutputNode->tableName.C_String());
  378. for (parameterCountIndex=0; parameterCountIndex < cpuOutputNode->parameterCount; parameterCountIndex++)
  379. {
  380. if (parameterCountIndex!=0)
  381. functionCallFriendlyText+=", ";
  382. switch (cpuOutputNode->parameterList[parameterCountIndex].type)
  383. {
  384. case SQLLPDT_POINTER:
  385. if (cpuOutputNode->parameterList[parameterCountIndex].size==4)
  386. functionCallFriendlyText+=RakNet::RakString("%p", cpuOutputNode->parameterList[parameterCountIndex].data.i);
  387. else
  388. functionCallFriendlyText+=RakNet::RakString("%p", cpuOutputNode->parameterList[parameterCountIndex].data.ll);
  389. break;
  390. case SQLLPDT_INTEGER:
  391. switch (cpuOutputNode->parameterList[parameterCountIndex].size)
  392. {
  393. case 1:
  394. functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.c);
  395. break;
  396. case 2:
  397. functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.s);
  398. break;
  399. case 4:
  400. functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.i);
  401. break;
  402. case 8:
  403. functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.ll);
  404. break;
  405. }
  406. break;
  407. case SQLLPDT_REAL:
  408. if (cpuOutputNode->parameterList[parameterCountIndex].size==sizeof(float))
  409. functionCallFriendlyText+=RakNet::RakString("%f", cpuOutputNode->parameterList[parameterCountIndex].data.f);
  410. else
  411. functionCallFriendlyText+=RakNet::RakString("%d", cpuOutputNode->parameterList[parameterCountIndex].data.d);
  412. break;
  413. case SQLLPDT_TEXT:
  414. functionCallFriendlyText+='"';
  415. if (cpuOutputNode->parameterList[parameterCountIndex].size>0)
  416. functionCallFriendlyText.AppendBytes(cpuOutputNode->parameterList[parameterCountIndex].data.cptr, cpuOutputNode->parameterList[parameterCountIndex].size);
  417. functionCallFriendlyText+='"';
  418. break;
  419. case SQLLPDT_IMAGE:
  420. functionCallFriendlyText+=RakNet::RakString("<%i byte image>", cpuOutputNode->parameterList[parameterCountIndex].size, cpuOutputNode->parameterList[parameterCountIndex].data.cptr);
  421. break;
  422. case SQLLPDT_BLOB:
  423. functionCallFriendlyText+=RakNet::RakString("<%i byte binary>", cpuOutputNode->parameterList[parameterCountIndex].size, cpuOutputNode->parameterList[parameterCountIndex].data.cptr);
  424. break;
  425. }
  426. }
  427. functionCallFriendlyText+=");";
  428. if (preparedStatements->insertIntoFunctionCalls==0)
  429. {
  430. rc = sqlite3_prepare_v2(dbHandle, "INSERT INTO "FUNCTION_CALL_TABLE" ("FUNCTION_CALL_FRIENDLY_TEXT", "FILE_COLUMN", "LINE_COLUMN", "TICK_COUNT_COLUMN", "AUTO_IP_COLUMN", "TIMESTAMP_NUMERIC_COLUMN" ,functionName) VALUES (?,?,?,?,?,?,?)", -1, &preparedStatements->insertIntoFunctionCalls, 0);
  431. if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
  432. {
  433. RakAssert("Failed INSERT INTO "FUNCTION_CALL_PARAMETERS_TABLE" in SQLiteServerLoggerPlugin.cpp" && 0);
  434. }
  435. }
  436. sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 1, functionCallFriendlyText.C_String(), -1, SQLITE_TRANSIENT);
  437. sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 2, cpuOutputNode->file.C_String(), -1, SQLITE_TRANSIENT);
  438. sqlite3_bind_int(preparedStatements->insertIntoFunctionCalls, 3, cpuOutputNode->line);
  439. sqlite3_bind_int(preparedStatements->insertIntoFunctionCalls, 4, cpuOutputNode->tickCount);
  440. sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 5, cpuOutputNode->ipAddressString, -1, SQLITE_TRANSIENT);
  441. sqlite3_bind_int(preparedStatements->insertIntoFunctionCalls, 6, (uint32_t) (cpuOutputNode->clientSendingTime));
  442. sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 7, cpuOutputNode->tableName.C_String(), -1, SQLITE_TRANSIENT);
  443. rc = sqlite3_step(preparedStatements->insertIntoFunctionCalls);
  444. sqlite3_reset(preparedStatements->insertIntoFunctionCalls);
  445. if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
  446. {
  447. RakAssert("Failed binding parameters to functionCalls in SQLiteServerLoggerPlugin.cpp" && 0);
  448. }
  449. // sqlite3_finalize(statement);
  450. // RakNet::RakString insertIntoFunctionCallsQuery("INSERT INTO 'functionCalls' ("FUNCTION_CALL_FRIENDLY_TEXT", "FILE_COLUMN", "LINE_COLUMN", "TICK_COUNT_COLUMN",functionName) VALUES ('%s','%s',%i,%i,'%s') ", functionCallFriendlyText.C_String(), file.C_String(), line, tickCount,tableName.C_String());
  451. // rc = sqlite3_exec(dbHandle,insertIntoFunctionCallsQuery.C_String(), 0, 0, &errorMsg);
  452. // RakAssert(rc==SQLITE_OK);
  453. // sqlite3_free(errorMsg);
  454. // Read last row id
  455. // Requires that this thread has its own connection
  456. sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(dbHandle);
  457. if (preparedStatements->insertIntoFunctionCallParameters==0)
  458. {
  459. rc = sqlite3_prepare_v2(dbHandle, "INSERT INTO functionCallParameters (functionId_fk, value) VALUES (?,?);", -1, &preparedStatements->insertIntoFunctionCallParameters, 0);
  460. RakAssert(rc==SQLITE_OK);
  461. sqlite3_bind_int64(preparedStatements->insertIntoFunctionCallParameters, 1, lastRowId);
  462. }
  463. // Insert into parameters table
  464. for (parameterCountIndex=0; parameterCountIndex < cpuOutputNode->parameterCount; parameterCountIndex++)
  465. {
  466. switch (cpuOutputNode->parameterList[parameterCountIndex].type)
  467. {
  468. case SQLLPDT_POINTER:
  469. case SQLLPDT_INTEGER:
  470. switch (cpuOutputNode->parameterList[parameterCountIndex].size)
  471. {
  472. case 1:
  473. sqlite3_bind_int(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.c);
  474. break;
  475. case 2:
  476. sqlite3_bind_int(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.s);
  477. break;
  478. case 4:
  479. sqlite3_bind_int(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.i);
  480. break;
  481. case 8:
  482. sqlite3_bind_int64(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.ll);
  483. break;
  484. }
  485. break;
  486. case SQLLPDT_REAL:
  487. if (cpuOutputNode->parameterList[parameterCountIndex].size==sizeof(float))
  488. sqlite3_bind_double(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.f);
  489. else
  490. sqlite3_bind_double(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.d);
  491. break;
  492. case SQLLPDT_TEXT:
  493. sqlite3_bind_text(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.cptr, cpuOutputNode->parameterList[parameterCountIndex].size, 0);
  494. break;
  495. case SQLLPDT_IMAGE:
  496. case SQLLPDT_BLOB:
  497. sqlite3_bind_blob(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.vptr, cpuOutputNode->parameterList[parameterCountIndex].size, DeleteBlobOrText);
  498. cpuOutputNode->parameterList[parameterCountIndex].DoNotFree();
  499. break;
  500. default:
  501. RakAssert("Hit invalid default in case label in SQLiteServerLoggerPlugin.cpp" && 0);
  502. }
  503. rc = sqlite3_step(preparedStatements->insertIntoFunctionCallParameters);
  504. sqlite3_reset(preparedStatements->insertIntoFunctionCallParameters);
  505. if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
  506. {
  507. RakAssert("Failed sqlite3_step to bind functionCall parameters in SQLiteServerLoggerPlugin.cpp" && 0);
  508. }
  509. }
  510. // if (statement)
  511. // sqlite3_finalize(statement);
  512. }
  513. else
  514. {
  515. sqlite3_stmt *pragmaTableInfo;
  516. RakNet::RakString pragmaQuery("PRAGMA table_info(%s)",cpuOutputNode->tableName.C_String());
  517. if (sqlite3_prepare_v2(
  518. dbHandle,
  519. pragmaQuery.C_String(),
  520. -1,
  521. &pragmaTableInfo,
  522. 0
  523. )!=SQLITE_OK)
  524. {
  525. RakAssert("Failed PRAGMA table_info for tableName in SQLiteServerLoggerPlugin.cpp" && 0);
  526. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  527. cpuOutputNode->parameterList[i].Free();
  528. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  529. return sqlThreadOutput;
  530. }
  531. int rc = sqlite3_step(pragmaTableInfo);
  532. DataStructures::List<RakNet::RakString> existingColumnNames;
  533. DataStructures::List<RakNet::RakString> existingColumnTypes;
  534. char *errorMsg;
  535. while (rc==SQLITE_ROW)
  536. {
  537. /*
  538. int nameColumn;
  539. for (int j=0; j < sqlite3_column_count(statement); j++)
  540. {
  541. if (strcmp(sqlite3_column_name(statement,j),"name")==0)
  542. {
  543. nameColumn=j;
  544. break;
  545. }
  546. }
  547. int typeColumn;
  548. for (int j=0; j < sqlite3_column_count(statement); j++)
  549. {
  550. if (strcmp(sqlite3_column_name(statement,j),"type")==0)
  551. {
  552. typeColumn=j;
  553. break;
  554. }
  555. }
  556. */
  557. const int nameColumn=1;
  558. const int typeColumn=2;
  559. RakAssert(strcmp(sqlite3_column_name(pragmaTableInfo,nameColumn),"name")==0);
  560. RakAssert(strcmp(sqlite3_column_name(pragmaTableInfo,typeColumn),"type")==0);
  561. RakNet::RakString columnName = sqlite3_column_text(pragmaTableInfo,nameColumn);
  562. RakNet::RakString columnType = sqlite3_column_text(pragmaTableInfo,typeColumn);
  563. existingColumnNames.Push(columnName, _FILE_AND_LINE_ );
  564. existingColumnTypes.Push(columnType, _FILE_AND_LINE_ );
  565. rc = sqlite3_step(pragmaTableInfo);
  566. }
  567. sqlite3_reset(pragmaTableInfo);
  568. sqlite3_finalize(pragmaTableInfo);
  569. if (rc==SQLITE_ERROR)
  570. {
  571. RakAssert("Failed sqlite3_step in SQLiteServerLoggerPlugin.cpp" && 0);
  572. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  573. cpuOutputNode->parameterList[i].Free();
  574. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  575. return sqlThreadOutput;
  576. }
  577. int existingColumnNamesIndex,insertingColumnNamesIndex;
  578. if (existingColumnNames.Size()==0)
  579. {
  580. RakNet::RakString createQuery("CREATE TABLE %s (rowId_pk INTEGER PRIMARY KEY, "FILE_COLUMN" TEXT, "LINE_COLUMN" INTEGER, "TICK_COUNT_COLUMN" INTEGER, "AUTO_IP_COLUMN" TEXT, "TIMESTAMP_TEXT_COLUMN" TIMESTAMP DATE DEFAULT (datetime('now','localtime')), "TIMESTAMP_NUMERIC_COLUMN" NUMERIC",cpuOutputNode->tableName.C_String());
  581. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  582. {
  583. createQuery+=", ";
  584. createQuery+=cpuOutputNode->insertingColumnNames[i];
  585. createQuery+=" ";
  586. createQuery+=GetSqlDataTypeName2(cpuOutputNode->parameterList[i].type);
  587. }
  588. createQuery+=" )";
  589. sqlite3_exec(dbHandle,
  590. createQuery.C_String(),
  591. 0, 0, &errorMsg);
  592. RakAssert(errorMsg==0);
  593. sqlite3_free(errorMsg);
  594. }
  595. else
  596. {
  597. // Compare what is there (columnNames,columnTypes) to what we are adding. Add what is missing
  598. bool alreadyExists;
  599. for (insertingColumnNamesIndex=0; insertingColumnNamesIndex<(int) cpuOutputNode->insertingColumnNames.Size(); insertingColumnNamesIndex++)
  600. {
  601. alreadyExists=false;
  602. for (existingColumnNamesIndex=0; existingColumnNamesIndex<(int) existingColumnNames.Size(); existingColumnNamesIndex++)
  603. {
  604. if (existingColumnNames[existingColumnNamesIndex]==cpuOutputNode->insertingColumnNames[insertingColumnNamesIndex])
  605. {
  606. // Type mismatch? If so, abort
  607. if (existingColumnTypes[existingColumnNamesIndex]!=GetSqlDataTypeName2(cpuOutputNode->parameterList[insertingColumnNamesIndex].type))
  608. {
  609. printf("Error: Column type mismatch. TableName=%s. ColumnName%s. Existing=%s. New=%s\n",
  610. cpuOutputNode->tableName.C_String(),
  611. existingColumnNames[existingColumnNamesIndex].C_String(),
  612. existingColumnTypes[existingColumnNamesIndex].C_String(),
  613. GetSqlDataTypeName2(cpuOutputNode->parameterList[insertingColumnNamesIndex].type)
  614. );
  615. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  616. cpuOutputNode->parameterList[i].Free();
  617. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  618. return sqlThreadOutput;
  619. }
  620. alreadyExists=true;
  621. break;
  622. }
  623. }
  624. if (alreadyExists==false)
  625. {
  626. sqlite3_exec(dbHandle,
  627. RakNet::RakString("ALTER TABLE %s ADD %s %s",
  628. cpuOutputNode->tableName.C_String(),
  629. cpuOutputNode->insertingColumnNames[insertingColumnNamesIndex].C_String(),
  630. GetSqlDataTypeName2(cpuOutputNode->parameterList[insertingColumnNamesIndex].type)
  631. ).C_String(),
  632. 0, 0, &errorMsg);
  633. RakAssert(errorMsg==0);
  634. sqlite3_free(errorMsg);
  635. }
  636. }
  637. }
  638. // Insert new row
  639. RakNet::RakString insertQuery("INSERT INTO %s (", cpuOutputNode->tableName.C_String());
  640. int parameterCountIndex;
  641. for (parameterCountIndex=0; parameterCountIndex<cpuOutputNode->parameterCount; parameterCountIndex++)
  642. {
  643. if (parameterCountIndex!=0)
  644. insertQuery+=", ";
  645. insertQuery+=cpuOutputNode->insertingColumnNames[parameterCountIndex].C_String();
  646. }
  647. // Add file and line to the end
  648. insertQuery+=", "FILE_COLUMN", "LINE_COLUMN", "TICK_COUNT_COLUMN", "AUTO_IP_COLUMN", "TIMESTAMP_NUMERIC_COLUMN" ) VALUES (";
  649. for (parameterCountIndex=0; parameterCountIndex<cpuOutputNode->parameterCount+5; parameterCountIndex++)
  650. {
  651. if (parameterCountIndex!=0)
  652. insertQuery+=", ?";
  653. else
  654. insertQuery+="?";
  655. }
  656. insertQuery+=")";
  657. sqlite3_stmt *customStatement;
  658. if (sqlite3_prepare_v2(
  659. dbHandle,
  660. insertQuery.C_String(),
  661. -1,
  662. &customStatement,
  663. 0
  664. )!=SQLITE_OK)
  665. {
  666. RakAssert("Failed second sqlite3_prepare_v2 in SQLiteServerLoggerPlugin.cpp" && 0);
  667. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  668. cpuOutputNode->parameterList[i].Free();
  669. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  670. return sqlThreadOutput;
  671. }
  672. for (parameterCountIndex=0; parameterCountIndex<cpuOutputNode->parameterCount; parameterCountIndex++)
  673. {
  674. switch (cpuOutputNode->parameterList[parameterCountIndex].type)
  675. {
  676. case SQLLPDT_POINTER:
  677. case SQLLPDT_INTEGER:
  678. switch (cpuOutputNode->parameterList[parameterCountIndex].size)
  679. {
  680. case 1:
  681. sqlite3_bind_int(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.c);
  682. break;
  683. case 2:
  684. sqlite3_bind_int(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.s);
  685. break;
  686. case 4:
  687. sqlite3_bind_int(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.i);
  688. break;
  689. case 8:
  690. sqlite3_bind_int64(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.ll);
  691. break;
  692. }
  693. break;
  694. case SQLLPDT_REAL:
  695. if (cpuOutputNode->parameterList[parameterCountIndex].size==sizeof(float))
  696. sqlite3_bind_double(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.f);
  697. else
  698. sqlite3_bind_double(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.d);
  699. break;
  700. case SQLLPDT_TEXT:
  701. sqlite3_bind_text(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.cptr, cpuOutputNode->parameterList[parameterCountIndex].size, DeleteBlobOrText);
  702. cpuOutputNode->parameterList[parameterCountIndex].DoNotFree();
  703. break;
  704. case SQLLPDT_IMAGE:
  705. case SQLLPDT_BLOB:
  706. sqlite3_bind_blob(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.vptr, cpuOutputNode->parameterList[parameterCountIndex].size, DeleteBlobOrText);
  707. cpuOutputNode->parameterList[parameterCountIndex].DoNotFree();
  708. break;
  709. }
  710. }
  711. // Add file and line to the end
  712. sqlite3_bind_text(customStatement, parameterCountIndex+1, cpuOutputNode->file.C_String(), (int) cpuOutputNode->file.GetLength(), SQLITE_TRANSIENT);
  713. sqlite3_bind_int(customStatement, parameterCountIndex+2, cpuOutputNode->line);
  714. sqlite3_bind_int(customStatement, parameterCountIndex+3, cpuOutputNode->tickCount);
  715. sqlite3_bind_text(customStatement, parameterCountIndex+4, cpuOutputNode->ipAddressString, -1, SQLITE_TRANSIENT);
  716. sqlite3_bind_int(customStatement, parameterCountIndex+5, (uint32_t) (cpuOutputNode->clientSendingTime));
  717. rc = sqlite3_step(customStatement);
  718. if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
  719. {
  720. RakAssert("Failed sqlite3_step to bind blobs in SQLiteServerLoggerPlugin.cpp" && 0);
  721. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  722. cpuOutputNode->parameterList[i].Free();
  723. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  724. return sqlThreadOutput;
  725. }
  726. sqlite3_finalize(customStatement);
  727. }
  728. sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
  729. for (int i=0; i < cpuOutputNode->parameterCount; i++)
  730. cpuOutputNode->parameterList[i].Free();
  731. return sqlThreadOutput;
  732. }
  733. SQLiteServerLoggerPlugin::SQLiteServerLoggerPlugin()
  734. {
  735. sessionManagementMode=CREATE_EACH_NAMED_DB_HANDLE;
  736. createDirectoryForFile=true;
  737. cpuThreadInput=0;
  738. dxtCompressionEnabled=false;
  739. }
  740. SQLiteServerLoggerPlugin::~SQLiteServerLoggerPlugin()
  741. {
  742. StopCPUSQLThreads();
  743. RakNet::OP_DELETE(cpuThreadInput,_FILE_AND_LINE_);
  744. CloseAllSessions();
  745. }
  746. void SQLiteServerLoggerPlugin::Update(void)
  747. {
  748. SQLite3ServerPlugin::Update();
  749. bool hadOutput=false;
  750. int arrayIndex;
  751. // unsigned int i;
  752. PushCpuThreadInputIfNecessary();
  753. while (cpuLoggerThreadPool.HasOutputFast() && cpuLoggerThreadPool.HasOutput())
  754. {
  755. CPUThreadOutput* cpuThreadOutput=cpuLoggerThreadPool.GetOutput();
  756. for (arrayIndex=0; arrayIndex < cpuThreadOutput->arraySize; arrayIndex++)
  757. {
  758. SQLThreadInput sqlThreadInput;
  759. CPUThreadOutputNode *outputNode = cpuThreadOutput->cpuOutputNodeArray[arrayIndex];
  760. sqlThreadInput.cpuOutputNode=outputNode;
  761. // bool alreadyHasLoggedInSession=false;
  762. int sessionIndex;
  763. for (sessionIndex=0; sessionIndex < loggedInSessions.Size(); sessionIndex++)
  764. {
  765. if (loggedInSessions[sessionIndex].systemAddress==outputNode->packet->systemAddress &&
  766. loggedInSessions[sessionIndex].sessionName==outputNode->dbIdentifier)
  767. {
  768. break;
  769. }
  770. }
  771. unsigned int idx;
  772. if (sessionManagementMode==USE_ANY_DB_HANDLE)
  773. {
  774. if (dbHandles.GetSize()>0)
  775. idx=0;
  776. else
  777. idx=-1;
  778. }
  779. else
  780. {
  781. idx = dbHandles.GetIndexOf(outputNode->dbIdentifier);
  782. if (sessionIndex==loggedInSessions.Size() && (createDirectoryForFile==true || idx==-1) && sessionManagementMode==CREATE_EACH_NAMED_DB_HANDLE)
  783. {
  784. // Create it, and set idx to the new one
  785. idx = CreateDBHandle(outputNode->dbIdentifier);
  786. }
  787. else if (idx==-1)
  788. {
  789. if (sessionManagementMode==CREATE_EACH_NAMED_DB_HANDLE || sessionManagementMode==CREATE_SHARED_NAMED_DB_HANDLE)
  790. {
  791. // Create it, and set idx to the new one
  792. idx = CreateDBHandle(outputNode->dbIdentifier);
  793. }
  794. if (sessionManagementMode==USE_NAMED_DB_HANDLE)
  795. {
  796. RakAssert("Can't find named DB handle\n" && 0);
  797. }
  798. }
  799. else
  800. {
  801. // Use idx
  802. }
  803. }
  804. if (idx==-1)
  805. {
  806. DeallocPacketUnified(outputNode->packet);
  807. RakNet::OP_DELETE(outputNode,_FILE_AND_LINE_);
  808. }
  809. else
  810. {
  811. if (sessionIndex==loggedInSessions.Size())
  812. {
  813. SessionNameAndSystemAddress sassy;
  814. sassy.sessionName=outputNode->dbIdentifier;
  815. sassy.systemAddress=outputNode->packet->systemAddress;
  816. sassy.referencedPointer=dbHandles[idx].dbHandle;
  817. RakNet::TimeMS curTime = RakNet::GetTimeMS();
  818. RakNet::TimeMS dbAge = curTime - dbHandles[idx].whenCreated;
  819. // RakNet::TimeMS timeDelta = outputNode->clientSendingTime - curTime;
  820. sassy.timestampDelta=dbAge - outputNode->clientSendingTime ;
  821. // sassy.dbAgeWhenCreated=dbHandles[idx].whenCreated;
  822. loggedInSessions.Push(sassy, _FILE_AND_LINE_ );
  823. sessionIndex=loggedInSessions.Size()-1;
  824. }
  825. DeallocPacketUnified(outputNode->packet);
  826. sqlThreadInput.dbHandle=dbHandles[idx].dbHandle;
  827. outputNode->clientSendingTime+=loggedInSessions[sessionIndex].timestampDelta;
  828. sqlLoggerThreadPool.AddInput(ExecSQLLoggingThread, sqlThreadInput);
  829. }
  830. }
  831. // RakNet::OP_DELETE_ARRAY(cpuThreadOutput->cpuOutputNodeArray);
  832. RakNet::OP_DELETE(cpuThreadOutput,_FILE_AND_LINE_);
  833. }
  834. while (sqlLoggerThreadPool.HasOutputFast() && sqlLoggerThreadPool.HasOutput())
  835. {
  836. hadOutput=true;
  837. RakNet::OP_DELETE(sqlLoggerThreadPool.GetOutput().cpuOutputNode,_FILE_AND_LINE_);
  838. }
  839. if (hadOutput)
  840. CloseUnreferencedSessions();
  841. }
  842. PluginReceiveResult SQLiteServerLoggerPlugin::OnReceive(Packet *packet)
  843. {
  844. PluginReceiveResult prr = SQLite3ServerPlugin::OnReceive(packet);
  845. if (prr!=RR_CONTINUE_PROCESSING)
  846. return prr;
  847. switch (packet->data[0])
  848. {
  849. case ID_SQLLITE_LOGGER:
  850. {
  851. RakNet::BitStream bitStream(packet->data, packet->length, false);
  852. bitStream.IgnoreBytes(1);
  853. RakNet::RakString dbIdentifier;
  854. bitStream.Read(dbIdentifier);
  855. if (sessionManagementMode==CREATE_EACH_NAMED_DB_HANDLE)
  856. {
  857. unsigned char senderAddr[32];
  858. packet->systemAddress.ToString(true,(char*) senderAddr);
  859. dbIdentifier+=':';
  860. dbIdentifier+=senderAddr;
  861. }
  862. CPUThreadInput *ti = LockCpuThreadInput();
  863. ti->cpuInputArray[ti->arraySize].packet=packet;
  864. // ti->cpuInputArray[ti->arraySize].whenMessageArrived=RakNet::GetTimeMS();
  865. ti->cpuInputArray[ti->arraySize].dbIdentifier=dbIdentifier;
  866. UnlockCpuThreadInput();
  867. /*
  868. unsigned int i;
  869. bool alreadyHasLoggedInSession=false;
  870. for (i=0; i < loggedInSessions.Size(); i++)
  871. {
  872. if (loggedInSessions[i].systemAddress==packet->systemAddress &&
  873. loggedInSessions[i].sessionName==dbIdentifier)
  874. {
  875. alreadyHasLoggedInSession=true;
  876. break;
  877. }
  878. }
  879. unsigned int idx;
  880. if (sessionManagementMode==USE_ANY_DB_HANDLE)
  881. {
  882. if (dbHandles.GetSize()>0)
  883. idx=0;
  884. else
  885. idx=-1;
  886. }
  887. else
  888. {
  889. idx = dbHandles.GetIndexOf(dbIdentifier);
  890. if (alreadyHasLoggedInSession==false && (createDirectoryForFile==true || idx==-1) && sessionManagementMode==CREATE_EACH_NAMED_DB_HANDLE)
  891. {
  892. // Create it, and set idx to the new one
  893. idx = CreateDBHandle(dbIdentifier);
  894. }
  895. else if (idx==-1)
  896. {
  897. if (sessionManagementMode==CREATE_EACH_NAMED_DB_HANDLE || sessionManagementMode==CREATE_SHARED_NAMED_DB_HANDLE)
  898. {
  899. // Create it, and set idx to the new one
  900. idx = CreateDBHandle(dbIdentifier);
  901. }
  902. if (sessionManagementMode==USE_NAMED_DB_HANDLE)
  903. {
  904. RakAssert("Can't find named DB handle\n" && 0);
  905. }
  906. }
  907. else
  908. {
  909. // Use idx
  910. }
  911. }
  912. if (idx==-1)
  913. {
  914. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  915. }
  916. if (alreadyHasLoggedInSession==false)
  917. {
  918. SessionNameAndSystemAddress sassy;
  919. sassy.sessionName=dbIdentifier;
  920. sassy.systemAddress=packet->systemAddress;
  921. sassy.referencedPointer=dbHandles[idx].dbHandle;
  922. loggedInSessions.Push(sassy);
  923. }
  924. SQLExecThreadInput input;
  925. input.dbHandle=dbHandles[idx].dbHandle;
  926. input.packet=packet;
  927. input.whenMessageArrived=RakNet::GetTimeMS()-dbHandles[idx].whenCreated;
  928. __sqlThreadPool.AddInput(ExecSQLLoggingThread, input);
  929. // printf("Pending Queries: %i\n", __sqlThreadPool.InputSize());
  930. */
  931. return RR_STOP_PROCESSING;
  932. }
  933. }
  934. return RR_CONTINUE_PROCESSING;
  935. }
  936. void SQLiteServerLoggerPlugin::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  937. {
  938. RakNet::RakString removedSession;
  939. unsigned int i=0;
  940. while (i < loggedInSessions.Size())
  941. {
  942. if (loggedInSessions[i].systemAddress==systemAddress)
  943. {
  944. removedSession=loggedInSessions[i].sessionName;
  945. loggedInSessions.RemoveAtIndexFast(i);
  946. /*
  947. unsigned int j;
  948. bool removedSessionReferenced=false;
  949. for (j=0; j < loggedInSessions.Size(); j++)
  950. {
  951. if (loggedInSessions[j].sessionName==removedSession)
  952. {
  953. removedSessionReferenced=true;
  954. break;
  955. }
  956. }
  957. if (removedSessionReferenced==false)
  958. {
  959. // if (__sqlThreadPool.InputSize()>0 || __sqlThreadPool.IsWorking())
  960. // return;
  961. // RemoveDBHandle(removedSession, sessionManagementMode==CREATE_EACH_NAMED_DB_HANDLE||sessionManagementMode==CREATE_ONE_NAMED_DB_HANDLE);
  962. }
  963. */
  964. }
  965. else
  966. i++;
  967. }
  968. CloseUnreferencedSessions();
  969. }
  970. void SQLiteServerLoggerPlugin::CloseUnreferencedSessions(void)
  971. {
  972. DataStructures::List<sqlite3 *> sessionNames;
  973. unsigned int j;
  974. for (j=0; j < loggedInSessions.Size(); j++)
  975. {
  976. if (sessionNames.GetIndexOf(loggedInSessions[j].referencedPointer)==-1)
  977. sessionNames.Push(loggedInSessions[j].referencedPointer, _FILE_AND_LINE_ );
  978. }
  979. DataStructures::List<sqlite3*> unreferencedHandles;
  980. bool isReferenced;
  981. for (unsigned int i=0; i < dbHandles.GetSize(); i++)
  982. {
  983. if (dbHandles[i].dbAutoCreated)
  984. {
  985. j=0;
  986. isReferenced=false;
  987. for (j=0; j < sessionNames.Size(); j++)
  988. {
  989. if (sessionNames[j]==dbHandles[i].dbHandle)
  990. {
  991. isReferenced=true;
  992. break;
  993. }
  994. }
  995. if (isReferenced==false)
  996. {
  997. unreferencedHandles.Push(dbHandles[i].dbHandle,_FILE_AND_LINE_);
  998. }
  999. }
  1000. }
  1001. if (unreferencedHandles.Size())
  1002. {
  1003. sqlLoggerThreadPool.LockInput();
  1004. if (sqlLoggerThreadPool.HasInputFast()==false)
  1005. {
  1006. RakSleep(100);
  1007. while (sqlLoggerThreadPool.NumThreadsWorking()>0)
  1008. RakSleep(30);
  1009. for (unsigned int k=0; k < unreferencedHandles.Size(); k++)
  1010. {
  1011. RemoveDBHandle(unreferencedHandles[k], true);
  1012. }
  1013. }
  1014. sqlLoggerThreadPool.UnlockInput();
  1015. if (dbHandles.GetSize()==0)
  1016. StopCPUSQLThreads();
  1017. }
  1018. }
  1019. void SQLiteServerLoggerPlugin::CloseAllSessions(void)
  1020. {
  1021. loggedInSessions.Clear(false, _FILE_AND_LINE_);
  1022. CloseUnreferencedSessions();
  1023. }
  1024. unsigned int SQLiteServerLoggerPlugin::CreateDBHandle(RakNet::RakString dbIdentifier)
  1025. {
  1026. if (sessionManagementMode!=CREATE_EACH_NAMED_DB_HANDLE && sessionManagementMode!=CREATE_SHARED_NAMED_DB_HANDLE)
  1027. return dbHandles.GetIndexOf(dbIdentifier);
  1028. RakNet::RakString filePath = newDatabaseFilePath;
  1029. if (createDirectoryForFile)
  1030. {
  1031. filePath+=dbIdentifier;
  1032. filePath.TerminateAtLastCharacter('.');
  1033. filePath.MakeFilePath();
  1034. time_t now;
  1035. struct tm *ts;
  1036. char buf[80];
  1037. /* Get the current time */
  1038. now = time(NULL);
  1039. /* Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz" */
  1040. ts = localtime(&now);
  1041. strftime(buf, sizeof(buf), "__%a_%Y-%m-%d__%H;%M", ts);
  1042. filePath+=buf;
  1043. filePath+=RakNet::RakString("__%i", RakNet::GetTimeMS());
  1044. filePath.MakeFilePath();
  1045. }
  1046. // With no file data, just creates the directory structure
  1047. WriteFileWithDirectories(filePath.C_String(), 0, 0);
  1048. RakNet::RakString fileSafeDbIdentifier = dbIdentifier;
  1049. fileSafeDbIdentifier.TerminateAtLastCharacter(':');
  1050. RakNet::RakString fileNameWithPath=filePath+fileSafeDbIdentifier;
  1051. // SQL Open this file, and register it
  1052. sqlite3 *database;
  1053. if (sqlite3_open_v2(fileNameWithPath.C_String(), &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0)!=SQLITE_OK)
  1054. {
  1055. RakAssert("sqlite3_open_v2 failed in SQLiteServerLoggerPlugin.cpp" && 0);
  1056. return -1;
  1057. }
  1058. if (AddDBHandle(dbIdentifier, database, true))
  1059. {
  1060. char *errorMsg;
  1061. int rc = sqlite3_exec(database,"PRAGMA synchronous=OFF", 0, 0, &errorMsg);
  1062. RakAssert(rc==SQLITE_OK);
  1063. sqlite3_free(errorMsg);
  1064. rc = sqlite3_exec(database,"PRAGMA count_changes=OFF", 0, 0, &errorMsg);
  1065. RakAssert(rc==SQLITE_OK);
  1066. sqlite3_free(errorMsg);
  1067. printf("Created %s\n", fileNameWithPath.C_String());
  1068. return dbHandles.GetIndexOf(dbIdentifier);
  1069. }
  1070. else
  1071. {
  1072. RakAssert("Failed to call AddDbHandle" && 0);
  1073. return -1;
  1074. }
  1075. return -1;
  1076. }
  1077. void SQLiteServerLoggerPlugin::SetSessionManagementMode(SessionManagementMode _sessionManagementMode, bool _createDirectoryForFile, const char *_newDatabaseFilePath)
  1078. {
  1079. sessionManagementMode=_sessionManagementMode;
  1080. createDirectoryForFile=_createDirectoryForFile;
  1081. newDatabaseFilePath=_newDatabaseFilePath;
  1082. newDatabaseFilePath.MakeFilePath();
  1083. }
  1084. void SQLiteServerLoggerPlugin::OnShutdown(void)
  1085. {
  1086. CloseAllSessions();
  1087. }
  1088. void SQLiteServerLoggerPlugin::StopCPUSQLThreads(void)
  1089. {
  1090. unsigned int i;
  1091. int j,k;
  1092. cpuLoggerThreadPool.StopThreads();
  1093. ClearCpuThreadInput();
  1094. for (i=0; i < cpuLoggerThreadPool.InputSize(); i++)
  1095. {
  1096. CPUThreadInput *cpuThreadInput = cpuLoggerThreadPool.GetInputAtIndex(i);
  1097. for (j=0; j < cpuThreadInput->arraySize; j++)
  1098. {
  1099. DeallocPacketUnified(cpuThreadInput->cpuInputArray[j].packet);
  1100. }
  1101. RakNet::OP_DELETE(cpuThreadInput,_FILE_AND_LINE_);
  1102. }
  1103. cpuLoggerThreadPool.ClearInput();
  1104. for (i=0; i < cpuLoggerThreadPool.OutputSize(); i++)
  1105. {
  1106. CPUThreadOutput *cpuThreadOutput = cpuLoggerThreadPool.GetOutputAtIndex(i);
  1107. for (j=0; j < cpuThreadOutput->arraySize; j++)
  1108. {
  1109. CPUThreadOutputNode *cpuThreadOutputNode = cpuThreadOutput->cpuOutputNodeArray[j];
  1110. DeallocPacketUnified(cpuThreadOutputNode->packet);
  1111. for (k=0; k < cpuThreadOutputNode->parameterCount; k++)
  1112. cpuThreadOutputNode->parameterList[k].Free();
  1113. RakNet::OP_DELETE(cpuThreadOutputNode,_FILE_AND_LINE_);
  1114. }
  1115. // RakNet::OP_DELETE_ARRAY(cpuThreadOutput->cpuOutputNodeArray,_FILE_AND_LINE_);
  1116. RakNet::OP_DELETE(cpuThreadOutput,_FILE_AND_LINE_);
  1117. }
  1118. cpuLoggerThreadPool.ClearOutput();
  1119. sqlLoggerThreadPool.StopThreads();
  1120. for (i=0; i < sqlLoggerThreadPool.InputSize(); i++)
  1121. RakNet::OP_DELETE(sqlLoggerThreadPool.GetInputAtIndex(i).cpuOutputNode,_FILE_AND_LINE_);
  1122. sqlLoggerThreadPool.ClearInput();
  1123. for (i=0; i < sqlLoggerThreadPool.OutputSize(); i++)
  1124. RakNet::OP_DELETE(sqlLoggerThreadPool.GetOutputAtIndex(i).cpuOutputNode,_FILE_AND_LINE_);
  1125. sqlLoggerThreadPool.ClearOutput();
  1126. }
  1127. void SQLiteServerLoggerPlugin::GetProcessingStatus(ProcessingStatus *processingStatus)
  1128. {
  1129. if (cpuThreadInput)
  1130. processingStatus->packetsBuffered=cpuThreadInput->arraySize;
  1131. else
  1132. processingStatus->packetsBuffered=0;
  1133. processingStatus->cpuPendingProcessing=cpuLoggerThreadPool.InputSize();
  1134. processingStatus->cpuProcessedAwaitingDeallocation=cpuLoggerThreadPool.OutputSize();
  1135. processingStatus->cpuNumThreadsWorking=cpuLoggerThreadPool.NumThreadsWorking();
  1136. processingStatus->sqlPendingProcessing=sqlLoggerThreadPool.InputSize();
  1137. processingStatus->sqlProcessedAwaitingDeallocation=sqlLoggerThreadPool.OutputSize();
  1138. processingStatus->sqlNumThreadsWorking=sqlLoggerThreadPool.NumThreadsWorking();
  1139. }
  1140. SQLiteServerLoggerPlugin::CPUThreadInput *SQLiteServerLoggerPlugin::LockCpuThreadInput(void)
  1141. {
  1142. if (cpuThreadInput==0)
  1143. {
  1144. cpuThreadInput=RakNet::OP_NEW<CPUThreadInput>(_FILE_AND_LINE_);
  1145. cpuThreadInput->arraySize=0;
  1146. whenCpuThreadInputAllocated=RakNet::GetTimeMS();
  1147. }
  1148. return cpuThreadInput;
  1149. }
  1150. void SQLiteServerLoggerPlugin::ClearCpuThreadInput(void)
  1151. {
  1152. if (cpuThreadInput!=0)
  1153. {
  1154. for (int i=0; i < cpuThreadInput->arraySize; i++)
  1155. DeallocPacketUnified(cpuThreadInput->cpuInputArray[i].packet);
  1156. RakNet::OP_DELETE(cpuThreadInput,_FILE_AND_LINE_);
  1157. cpuThreadInput=0;
  1158. }
  1159. }
  1160. void SQLiteServerLoggerPlugin::UnlockCpuThreadInput(void)
  1161. {
  1162. cpuThreadInput->arraySize++;
  1163. if (cpuThreadInput->arraySize==MAX_PACKETS_PER_CPU_INPUT_THREAD)
  1164. PushCpuThreadInput();
  1165. else
  1166. PushCpuThreadInputIfNecessary();
  1167. }
  1168. void SQLiteServerLoggerPlugin::CancelLockCpuThreadInput(void)
  1169. {
  1170. if (cpuThreadInput->arraySize==0)
  1171. {
  1172. RakNet::OP_DELETE(cpuThreadInput,_FILE_AND_LINE_);
  1173. cpuThreadInput=0;
  1174. }
  1175. }
  1176. void SQLiteServerLoggerPlugin::PushCpuThreadInput(void)
  1177. {
  1178. // cpu threads can probably be as many as I want
  1179. if (cpuLoggerThreadPool.WasStarted()==false)
  1180. {
  1181. if (dxtCompressionEnabled)
  1182. cpuLoggerThreadPool.StartThreads(1,0,InitDxt, DeinitDxt);
  1183. else
  1184. cpuLoggerThreadPool.StartThreads(1,0,0, 0);
  1185. }
  1186. // sql logger threads should probably be limited to 1 since I'm doing transaction locks and calling sqlite3_last_insert_rowid
  1187. if (sqlLoggerThreadPool.WasStarted()==false)
  1188. sqlLoggerThreadPool.StartThreads(1,0, SQLLoggerThreadAllocPreparedStatements, SQLLoggerThreadDeallocPreparedStatements);
  1189. cpuLoggerThreadPool.AddInput(ExecCPULoggingThread, cpuThreadInput);
  1190. cpuThreadInput=0;
  1191. }
  1192. void SQLiteServerLoggerPlugin::PushCpuThreadInputIfNecessary(void)
  1193. {
  1194. RakNet::TimeMS curTime = RakNet::GetTimeMS();
  1195. if (cpuThreadInput && curTime-whenCpuThreadInputAllocated>MAX_TIME_TO_BUFFER_PACKETS)
  1196. PushCpuThreadInput();
  1197. }
  1198. void SQLiteServerLoggerPlugin::OnAttach(void)
  1199. {
  1200. }
  1201. void SQLiteServerLoggerPlugin::OnDetach(void)
  1202. {
  1203. }
  1204. void SQLiteServerLoggerPlugin::SetEnableDXTCompression(bool enable)
  1205. {
  1206. dxtCompressionEnabled=enable;
  1207. }
粤ICP备19079148号