All pastes #466408 Raw Edit

MaNGOS bootup speed patch

public text v1 · immutable
#466408 ·published 2007-04-30 23:39 UTC
rendered paste body
Index: game/LootMgr.cpp
===================================================================
--- game/LootMgr.cpp	(revision 3551)
+++ game/LootMgr.cpp	(working copy)
@@ -53,6 +53,38 @@
     LootTemplates_Disenchant.clear();
 }
 
+char const *formatString2( char const *format, ... )
+{
+    va_list        argptr;
+    #define    MAX_FMT_STRING    32000
+    static char        temp_buffer[MAX_FMT_STRING];
+    static char        string[MAX_FMT_STRING];
+    static int        index = 0;
+    char    *buf;
+    int len;
+
+    va_start(argptr, format);
+    vsnprintf(temp_buffer,MAX_FMT_STRING, format, argptr);
+    va_end(argptr);
+
+    len = strlen(temp_buffer);
+
+    if( len >= MAX_FMT_STRING )
+        return "ERROR";
+
+    if (len + index >= MAX_FMT_STRING-1)
+    {
+        index = 0;
+    }
+
+    buf = &string[index];
+    memcpy( buf, temp_buffer, len+1 );
+
+    index += len + 1;
+
+    return buf;
+}
+
 void LoadLootTable(LootStore& lootstore,char const* tablename)
 {
     LootStore::iterator tab;
@@ -63,41 +95,115 @@
     int32 questchance;
     uint32 count = 0;
     bool is_ffa = true;
+	FILE		*pOut, *pIn;
 
     sLog.outString( "%s :", tablename);
 
-    QueryResult *result = sDatabase.PQuery("SELECT `entry`, `item`, `ChanceOrRef`, `QuestChanceOrGroup`, `mincount`, `maxcount`, `quest_freeforall` FROM `%s`",tablename);
+	if ( (pIn = fopen( formatString2("cache/%s.cache", tablename), "rb")) == NULL )
+	{// UQ1: Trying .cache file for faster loading time... If one does not exist, create it from DB.
+		// Make a cache directory...
+		system("mkdir cache");
 
-    if (result)
-    {
-        barGoLink bar(result->GetRowCount());
+	    if ( (pOut = fopen( formatString2("cache/%s.cache", tablename), "wb")) == NULL )
+	    {
+	    }
 
-        std::ostringstream ssNonLootableItems;
+        QueryResult *result = sDatabase.PQuery("SELECT `entry`, `item`, `ChanceOrRef`, `QuestChanceOrGroup`, `mincount`, `maxcount`, `quest_freeforall` FROM `%s`",tablename);
 
-        do
-        {
-            Field *fields = result->Fetch();
-            bar.step();
+	    uint64 row_count = result->GetRowCount();
+	    fwrite( &row_count, sizeof(uint64), 1, pOut );
 
-            entry = fields[0].GetUInt32();
-            item = fields[1].GetUInt32();;
-            chance = fields[2].GetFloat();
-            questchance = int32(fields[3].GetUInt32());
-            mincount = fields[4].GetUInt32();
-            maxcount = fields[5].GetUInt32();
-            is_ffa = fields[6].GetBool();
+	    if (result)
+	    {
+            barGoLink bar(result->GetRowCount());
 
-            ItemPrototype const *proto = objmgr.GetItemPrototype(item);
+            std::ostringstream ssNonLootableItems;
 
-            if(!proto)
+            do
             {
-                ssNonLootableItems << "loot entry = " << entry << " item = " << item << " mincount = " << mincount << " maxcount = " << maxcount << " (not exist)\n";
-                continue;
-            }
+                Field *fields = result->Fetch();
+                bar.step();
 
-            displayid = proto->DisplayInfoID;
+                entry = fields[0].GetUInt32();
+	    		fwrite( &entry, sizeof(uint32), 1, pOut );
+                item = fields[1].GetUInt32();;
+			    fwrite( &item, sizeof(uint32), 1, pOut );
+                chance = fields[2].GetFloat();
+	    		fwrite( &chance, sizeof(float), 1, pOut );
+                questchance = int32(fields[3].GetUInt32());
+			    fwrite( &questchance, sizeof(uint32), 1, pOut );
+                mincount = fields[4].GetUInt32();
+	    		fwrite( &mincount, sizeof(uint32), 1, pOut );
+                maxcount = fields[5].GetUInt32();
+			    fwrite( &maxcount, sizeof(uint32), 1, pOut );
+                is_ffa = fields[6].GetBool();
+	    		fwrite( &is_ffa, sizeof(bool), 1, pOut );
 
-            // non-quest (maybe group) loot with low chance
+                ItemPrototype const *proto = objmgr.GetItemPrototype(item);
+
+                if(!proto)
+                {
+                    ssNonLootableItems << "loot entry = " << entry << " item = " << item << " mincount = " << mincount << " maxcount = " << maxcount << " (not exist)\n";
+                    continue;
+                }
+
+                displayid = proto->DisplayInfoID;
+		    	fwrite( &displayid, sizeof(uint32), 1, pOut );
+
+                // non-quest (maybe group) loot with low chance
+                if( chance >= 0 && chance < 0.000001 && questchance <= 0 )
+                {
+                    ssNonLootableItems << "loot entry = " << entry << " item = " << item << " mincount = " << mincount << " maxcount = " << maxcount << " (no chance)\n";
+                    continue;
+                }
+
+                lootstore[entry].push_back( LootStoreItem(item, displayid, chance, questchance,is_ffa,mincount,maxcount) );
+
+                count++;
+            } while (result->NextRow());
+
+            delete result;
+
+            sLog.outString( "" );
+            sLog.outString( ">> Loaded %u loot definitions", count );
+			sLog.outString( ">> Cache file %s created for next boot.", formatString2("cache/%s.cache", tablename) );
+            if(ssNonLootableItems.str().size() > 0)
+                sLog.outErrorDb("Some items can't be succesfully looted: not exist or have in chance field value < 0.000001 with quest chance ==0 in `%s` DB table . List:\n%s",tablename,ssNonLootableItems.str().c_str());
+        }
+        else
+        {
+            sLog.outString( "" );
+            sLog.outErrorDb( ">> Loaded 0 loot definitions. DB table `%s` is empty.",tablename );
+        }
+
+	    fclose( pOut );
+	}
+	else
+	{// Use .cache file!
+		int loop = 0;
+		uint64 row_count = 0;
+		
+		fread( &row_count, sizeof(uint64), 1, pIn );
+
+		barGoLink bar(row_count);
+
+        std::ostringstream ssNonLootableItems;
+
+		for (loop = 0; loop < row_count; loop++)
+		{
+			bar.step();
+
+	   	    fread( &entry, sizeof(uint32), 1, pIn );
+		    fread( &item, sizeof(uint32), 1, pIn );
+	   		fread( &chance, sizeof(float), 1, pIn );
+		    fread( &questchance, sizeof(uint32), 1, pIn );
+	   		fread( &mincount, sizeof(uint32), 1, pIn );
+		    fread( &maxcount, sizeof(uint32), 1, pIn );
+	   		fread( &is_ffa, sizeof(bool), 1, pIn );
+
+	    	fread( &displayid, sizeof(uint32), 1, pIn );
+
+    		// non-quest (maybe group) loot with low chance
             if( chance >= 0 && chance < 0.000001 && questchance <= 0 )
             {
                 ssNonLootableItems << "loot entry = " << entry << " item = " << item << " mincount = " << mincount << " maxcount = " << maxcount << " (no chance)\n";
@@ -106,21 +212,13 @@
 
             lootstore[entry].push_back( LootStoreItem(item, displayid, chance, questchance,is_ffa,mincount,maxcount) );
 
-            count++;
-        } while (result->NextRow());
+			count++;
+		}
 
-        delete result;
+		fclose( pIn );
 
-        sLog.outString( "" );
-        sLog.outString( ">> Loaded %u loot definitions", count );
-        if(ssNonLootableItems.str().size() > 0)
-            sLog.outErrorDb("Some items can't be succesfully looted: not exist or have in chance field value < 0.000001 with quest chance ==0 in `%s` DB table . List:\n%s",tablename,ssNonLootableItems.str().c_str());
-    }
-    else
-    {
-        sLog.outString( "" );
-        sLog.outErrorDb( ">> Loaded 0 loot definitions. DB table `%s` is empty.",tablename );
-    }
+		sLog.outString( ">> Loaded %u loot definitions from cache.", count );
+	}
 }
 
 void LoadLootTables()