From 92c59963f82f81aa3202657e7fdbb2592924ede3 Mon Sep 17 00:00:00 2001 From: "cedeel@gmail.com" Date: Thu, 14 Jun 2012 13:06:06 +0000 Subject: Attempt to bring sanity to newlines across systems. git-svn-id: http://mc-server.googlecode.com/svn/trunk@606 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/WorldStorage.cpp | 758 ++++++++++++++++++++++++------------------------ 1 file changed, 379 insertions(+), 379 deletions(-) (limited to 'source/WorldStorage.cpp') diff --git a/source/WorldStorage.cpp b/source/WorldStorage.cpp index c9ca69659..ce1c11322 100644 --- a/source/WorldStorage.cpp +++ b/source/WorldStorage.cpp @@ -1,379 +1,379 @@ - -// WorldStorage.cpp - -// Implements the cWorldStorage class representing the chunk loading / saving thread - -// To add a new storage schema, implement a cWSSchema descendant and add it to cWorldStorage::InitSchemas() - -#include "Globals.h" -#include "WorldStorage.h" -#include "WSSCompact.h" -#include "WSSAnvil.h" -#include "cWorld.h" -#include "cChunkGenerator.h" -#include "cEntity.h" -#include "cBlockEntity.h" -#include "BlockID.h" - - - - - -/// Example storage schema - forgets all chunks ;) -class cWSSForgetful : - public cWSSchema -{ -public: - cWSSForgetful(cWorld * a_World) : cWSSchema(a_World) {} - -protected: - // cWSSchema overrides: - virtual bool LoadChunk(const cChunkCoords & a_Chunk) override {return false; } - virtual bool SaveChunk(const cChunkCoords & a_Chunk) override {return true; } - virtual const AString GetName(void) const override {return "forgetful"; } -} ; - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cWorldStorage: - -cWorldStorage::cWorldStorage(void) : - super("cWorldStorage"), - m_World(NULL), - m_SaveSchema(NULL) -{ -} - - - - - -cWorldStorage::~cWorldStorage() -{ - for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) - { - delete *itr; - } // for itr - m_Schemas[] - m_LoadQueue.clear(); - m_SaveQueue.clear(); -} - - - - - -bool cWorldStorage::Start(cWorld * a_World, const AString & a_StorageSchemaName) -{ - m_World = a_World; - m_StorageSchemaName = a_StorageSchemaName; - InitSchemas(); - - return super::Start(); -} - - - - - -void cWorldStorage::WaitForFinish(void) -{ - LOG("Waiting for the world storage to finish saving"); - - { - // Cancel all loading requests: - cCSLock Lock(m_CSQueues); - m_LoadQueue.clear(); - } - - // Wait for the saving to finish: - WaitForQueuesEmpty(); - - // Wait for the thread to finish: - m_ShouldTerminate = true; - m_Event.Set(); - m_evtRemoved.Set(); // Wake up anybody waiting in the WaitForQueuesEmpty() method - super::Wait(); - LOG("World storage thread finished"); -} - - - - - -void cWorldStorage::WaitForQueuesEmpty(void) -{ - cCSLock Lock(m_CSQueues); - while (!m_ShouldTerminate && (!m_LoadQueue.empty() || !m_SaveQueue.empty())) - { - cCSUnlock Unlock(Lock); - m_evtRemoved.Wait(); - } -} - - - - - -int cWorldStorage::GetLoadQueueLength(void) -{ - cCSLock Lock(m_CSQueues); - return (int)m_LoadQueue.size(); -} - - - - - -int cWorldStorage::GetSaveQueueLength(void) -{ - cCSLock Lock(m_CSQueues); - return (int)m_SaveQueue.size(); -} - - - - - -void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) -{ - // Queues the chunk for loading; if not loaded, the chunk will be generated - { - cCSLock Lock(m_CSQueues); - - // Check if already in the queue: - for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr) - { - if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ) && (itr->m_Generate == a_Generate)) - { - return; - } - } - m_LoadQueue.push_back(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate)); - } - - m_Event.Set(); -} - - - - - -void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) -{ - { - cCSLock Lock(m_CSQueues); - m_SaveQueue.remove (cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); // Don't add twice - m_SaveQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); - } - m_Event.Set(); -} - - - - - -void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ) -{ - cCSLock Lock(m_CSQueues); - for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr) - { - if ((itr->m_ChunkX != a_ChunkX) || (itr->m_ChunkY != a_ChunkY) || (itr->m_ChunkZ != a_ChunkZ)) - { - continue; - } - m_LoadQueue.erase(itr); - Lock.Unlock(); - m_evtRemoved.Set(); - return; - } // for itr - m_LoadQueue[] -} - - - - - -void cWorldStorage::UnqueueSave(const cChunkCoords & a_Chunk) -{ - { - cCSLock Lock(m_CSQueues); - m_SaveQueue.remove(a_Chunk); - } - m_evtRemoved.Set(); -} - - - - - -void cWorldStorage::InitSchemas(void) -{ - // The first schema added is considered the default - m_Schemas.push_back(new cWSSCompact (m_World)); - m_Schemas.push_back(new cWSSAnvil (m_World)); - m_Schemas.push_back(new cWSSForgetful(m_World)); - // Add new schemas here - - if (NoCaseCompare(m_StorageSchemaName, "default") == 0) - { - m_SaveSchema = m_Schemas.front(); - return; - } - for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) - { - if (NoCaseCompare((*itr)->GetName(), m_StorageSchemaName) == 0) - { - m_SaveSchema = *itr; - return; - } - } // for itr - m_Schemas[] - - // Unknown schema selected, let the admin know: - LOGWARNING("Unknown storage schema name \"%s\". Using default (\"%s\"). Available schemas:", - m_StorageSchemaName.c_str(), m_SaveSchema->GetName().c_str() - ); - for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) - { - LOGWARNING("\t\"%s\"", (*itr)->GetName().c_str()); - } - m_SaveSchema = m_Schemas.front(); -} - - - - - -void cWorldStorage::Execute(void) -{ - while (!m_ShouldTerminate) - { - m_Event.Wait(); - - // Process both queues until they are empty again: - bool HasMore; - do - { - HasMore = false; - if (m_ShouldTerminate) - { - return; - } - - HasMore = LoadOneChunk(); - HasMore = HasMore | SaveOneChunk(); - m_evtRemoved.Set(); - } while (HasMore); - } -} - - - - - -bool cWorldStorage::LoadOneChunk(void) -{ - sChunkLoad ToLoad(0, 0, 0, false); - bool HasMore; - bool ShouldLoad = false; - { - cCSLock Lock(m_CSQueues); - if (!m_LoadQueue.empty()) - { - ToLoad = m_LoadQueue.front(); - m_LoadQueue.pop_front(); - ShouldLoad = true; - } - HasMore = !m_LoadQueue.empty(); - } - - if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ)) - { - if (ToLoad.m_Generate) - { - // The chunk couldn't be loaded, generate it: - m_World->GetGenerator().QueueGenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); - } - else - { - // TODO: Notify the world that the load has failed: - // m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); - } - } - return HasMore; -} - - - - - -bool cWorldStorage::SaveOneChunk(void) -{ - cChunkCoords Save(0, 0, 0); - bool HasMore; - bool ShouldSave = false; - { - cCSLock Lock(m_CSQueues); - if (!m_SaveQueue.empty()) - { - Save = m_SaveQueue.front(); - m_SaveQueue.pop_front(); - ShouldSave = true; - } - HasMore = !m_SaveQueue.empty(); - } - if (ShouldSave && m_World->IsChunkValid(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ)) - { - m_World->MarkChunkSaving(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ); - if (m_SaveSchema->SaveChunk(Save)) - { - m_World->MarkChunkSaved(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ); - } - else - { - LOGWARNING("Cannot save chunk [%d, %d, %d]", Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ); - } - } - return HasMore; -} - - - - - -bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) -{ - if (m_World->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ)) - { - // Already loaded (can happen, since the queue is async) - return true; - } - - cChunkCoords Coords(a_ChunkX, a_ChunkY, a_ChunkZ); - - // First try the schema that is used for saving - if (m_SaveSchema->LoadChunk(Coords)) - { - return true; - } - - // If it didn't have the chunk, try all the other schemas: - for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) - { - if (((*itr) != m_SaveSchema) && (*itr)->LoadChunk(Coords)) - { - return true; - } - } - - // Notify the chunk owner that the chunk failed to load (sets cChunk::m_HasLoadFailed to true): - m_World->ChunkLoadFailed(a_ChunkX, a_ChunkY, a_ChunkZ); - - return false; -} - - - - - + +// WorldStorage.cpp + +// Implements the cWorldStorage class representing the chunk loading / saving thread + +// To add a new storage schema, implement a cWSSchema descendant and add it to cWorldStorage::InitSchemas() + +#include "Globals.h" +#include "WorldStorage.h" +#include "WSSCompact.h" +#include "WSSAnvil.h" +#include "cWorld.h" +#include "cChunkGenerator.h" +#include "cEntity.h" +#include "cBlockEntity.h" +#include "BlockID.h" + + + + + +/// Example storage schema - forgets all chunks ;) +class cWSSForgetful : + public cWSSchema +{ +public: + cWSSForgetful(cWorld * a_World) : cWSSchema(a_World) {} + +protected: + // cWSSchema overrides: + virtual bool LoadChunk(const cChunkCoords & a_Chunk) override {return false; } + virtual bool SaveChunk(const cChunkCoords & a_Chunk) override {return true; } + virtual const AString GetName(void) const override {return "forgetful"; } +} ; + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cWorldStorage: + +cWorldStorage::cWorldStorage(void) : + super("cWorldStorage"), + m_World(NULL), + m_SaveSchema(NULL) +{ +} + + + + + +cWorldStorage::~cWorldStorage() +{ + for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) + { + delete *itr; + } // for itr - m_Schemas[] + m_LoadQueue.clear(); + m_SaveQueue.clear(); +} + + + + + +bool cWorldStorage::Start(cWorld * a_World, const AString & a_StorageSchemaName) +{ + m_World = a_World; + m_StorageSchemaName = a_StorageSchemaName; + InitSchemas(); + + return super::Start(); +} + + + + + +void cWorldStorage::WaitForFinish(void) +{ + LOG("Waiting for the world storage to finish saving"); + + { + // Cancel all loading requests: + cCSLock Lock(m_CSQueues); + m_LoadQueue.clear(); + } + + // Wait for the saving to finish: + WaitForQueuesEmpty(); + + // Wait for the thread to finish: + m_ShouldTerminate = true; + m_Event.Set(); + m_evtRemoved.Set(); // Wake up anybody waiting in the WaitForQueuesEmpty() method + super::Wait(); + LOG("World storage thread finished"); +} + + + + + +void cWorldStorage::WaitForQueuesEmpty(void) +{ + cCSLock Lock(m_CSQueues); + while (!m_ShouldTerminate && (!m_LoadQueue.empty() || !m_SaveQueue.empty())) + { + cCSUnlock Unlock(Lock); + m_evtRemoved.Wait(); + } +} + + + + + +int cWorldStorage::GetLoadQueueLength(void) +{ + cCSLock Lock(m_CSQueues); + return (int)m_LoadQueue.size(); +} + + + + + +int cWorldStorage::GetSaveQueueLength(void) +{ + cCSLock Lock(m_CSQueues); + return (int)m_SaveQueue.size(); +} + + + + + +void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) +{ + // Queues the chunk for loading; if not loaded, the chunk will be generated + { + cCSLock Lock(m_CSQueues); + + // Check if already in the queue: + for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr) + { + if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ) && (itr->m_Generate == a_Generate)) + { + return; + } + } + m_LoadQueue.push_back(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate)); + } + + m_Event.Set(); +} + + + + + +void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + { + cCSLock Lock(m_CSQueues); + m_SaveQueue.remove (cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); // Don't add twice + m_SaveQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); + } + m_Event.Set(); +} + + + + + +void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + cCSLock Lock(m_CSQueues); + for (sChunkLoadQueue::iterator itr = m_LoadQueue.begin(); itr != m_LoadQueue.end(); ++itr) + { + if ((itr->m_ChunkX != a_ChunkX) || (itr->m_ChunkY != a_ChunkY) || (itr->m_ChunkZ != a_ChunkZ)) + { + continue; + } + m_LoadQueue.erase(itr); + Lock.Unlock(); + m_evtRemoved.Set(); + return; + } // for itr - m_LoadQueue[] +} + + + + + +void cWorldStorage::UnqueueSave(const cChunkCoords & a_Chunk) +{ + { + cCSLock Lock(m_CSQueues); + m_SaveQueue.remove(a_Chunk); + } + m_evtRemoved.Set(); +} + + + + + +void cWorldStorage::InitSchemas(void) +{ + // The first schema added is considered the default + m_Schemas.push_back(new cWSSCompact (m_World)); + m_Schemas.push_back(new cWSSAnvil (m_World)); + m_Schemas.push_back(new cWSSForgetful(m_World)); + // Add new schemas here + + if (NoCaseCompare(m_StorageSchemaName, "default") == 0) + { + m_SaveSchema = m_Schemas.front(); + return; + } + for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) + { + if (NoCaseCompare((*itr)->GetName(), m_StorageSchemaName) == 0) + { + m_SaveSchema = *itr; + return; + } + } // for itr - m_Schemas[] + + // Unknown schema selected, let the admin know: + LOGWARNING("Unknown storage schema name \"%s\". Using default (\"%s\"). Available schemas:", + m_StorageSchemaName.c_str(), m_SaveSchema->GetName().c_str() + ); + for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) + { + LOGWARNING("\t\"%s\"", (*itr)->GetName().c_str()); + } + m_SaveSchema = m_Schemas.front(); +} + + + + + +void cWorldStorage::Execute(void) +{ + while (!m_ShouldTerminate) + { + m_Event.Wait(); + + // Process both queues until they are empty again: + bool HasMore; + do + { + HasMore = false; + if (m_ShouldTerminate) + { + return; + } + + HasMore = LoadOneChunk(); + HasMore = HasMore | SaveOneChunk(); + m_evtRemoved.Set(); + } while (HasMore); + } +} + + + + + +bool cWorldStorage::LoadOneChunk(void) +{ + sChunkLoad ToLoad(0, 0, 0, false); + bool HasMore; + bool ShouldLoad = false; + { + cCSLock Lock(m_CSQueues); + if (!m_LoadQueue.empty()) + { + ToLoad = m_LoadQueue.front(); + m_LoadQueue.pop_front(); + ShouldLoad = true; + } + HasMore = !m_LoadQueue.empty(); + } + + if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ)) + { + if (ToLoad.m_Generate) + { + // The chunk couldn't be loaded, generate it: + m_World->GetGenerator().QueueGenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); + } + else + { + // TODO: Notify the world that the load has failed: + // m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ); + } + } + return HasMore; +} + + + + + +bool cWorldStorage::SaveOneChunk(void) +{ + cChunkCoords Save(0, 0, 0); + bool HasMore; + bool ShouldSave = false; + { + cCSLock Lock(m_CSQueues); + if (!m_SaveQueue.empty()) + { + Save = m_SaveQueue.front(); + m_SaveQueue.pop_front(); + ShouldSave = true; + } + HasMore = !m_SaveQueue.empty(); + } + if (ShouldSave && m_World->IsChunkValid(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ)) + { + m_World->MarkChunkSaving(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ); + if (m_SaveSchema->SaveChunk(Save)) + { + m_World->MarkChunkSaved(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ); + } + else + { + LOGWARNING("Cannot save chunk [%d, %d, %d]", Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ); + } + } + return HasMore; +} + + + + + +bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + if (m_World->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ)) + { + // Already loaded (can happen, since the queue is async) + return true; + } + + cChunkCoords Coords(a_ChunkX, a_ChunkY, a_ChunkZ); + + // First try the schema that is used for saving + if (m_SaveSchema->LoadChunk(Coords)) + { + return true; + } + + // If it didn't have the chunk, try all the other schemas: + for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) + { + if (((*itr) != m_SaveSchema) && (*itr)->LoadChunk(Coords)) + { + return true; + } + } + + // Notify the chunk owner that the chunk failed to load (sets cChunk::m_HasLoadFailed to true): + m_World->ChunkLoadFailed(a_ChunkX, a_ChunkY, a_ChunkZ); + + return false; +} + + + + + -- cgit v1.2.3