mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-11-04 06:32:00 +00:00 
			
		
		
		
	Abstracted the CDClient tables
There is now an option to utilize shared memory for some CDClient tables by adding `CD_PROVIDER_MEMORY=1` to the CMakeVariables.txt file. Allows masterconfig.ini to specify another run command for the world server, to allow for easier debugging through `valgrind`.
This commit is contained in:
		@@ -171,6 +171,9 @@ void CatchUnhandled(int sig) {
 | 
			
		||||
        ErrorCallback,
 | 
			
		||||
        nullptr);
 | 
			
		||||
 | 
			
		||||
    // Print error code
 | 
			
		||||
    printf("Error code: %d\n", sig);
 | 
			
		||||
 | 
			
		||||
    struct bt_ctx ctx = {state, 0};
 | 
			
		||||
    Bt(state);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,12 +34,19 @@ void dConfig::ProcessLine(const std::string& line) {
 | 
			
		||||
	   seglist.push_back(segment);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (seglist.size() != 2) return;
 | 
			
		||||
	if (seglist.size() < 2) return;
 | 
			
		||||
 | 
			
		||||
	// Segment #1 is combined with the rest of the line to form the value
 | 
			
		||||
	std::string key = seglist[0];
 | 
			
		||||
	std::string value = seglist[1];
 | 
			
		||||
	for (size_t i = 2; i < seglist.size(); ++i) {
 | 
			
		||||
		value += "=" + seglist[i];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Make sure that on Linux, we remove special characters:
 | 
			
		||||
	if (!seglist[1].empty() && seglist[1][seglist[1].size() - 1] == '\r')
 | 
			
		||||
    	seglist[1].erase(seglist[1].size() - 1);
 | 
			
		||||
	if (!value.empty() && value[value.size() - 1] == '\r')
 | 
			
		||||
    	value.erase(value.size() - 1);
 | 
			
		||||
 | 
			
		||||
	m_Keys.push_back(seglist[0]);
 | 
			
		||||
	m_Values.push_back(seglist[1]);
 | 
			
		||||
	m_Keys.push_back(key);
 | 
			
		||||
	m_Values.push_back(value);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								dDatabase/CDAbstractProvider.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								dDatabase/CDAbstractProvider.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "GeneralUtils.h"
 | 
			
		||||
 | 
			
		||||
#include "Game.h"
 | 
			
		||||
#include "dLogger.h"
 | 
			
		||||
#include "dServer.h"
 | 
			
		||||
 | 
			
		||||
#include "CDTable.h"
 | 
			
		||||
 | 
			
		||||
template <
 | 
			
		||||
    typename KeyType,
 | 
			
		||||
    typename MappedType
 | 
			
		||||
>
 | 
			
		||||
class CDAbstractProvider
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual void LoadClient() = 0;
 | 
			
		||||
    virtual void LoadHost() = 0;
 | 
			
		||||
 | 
			
		||||
    virtual const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) = 0;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										124
									
								
								dDatabase/CDAbstractSharedMemoryMap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								dDatabase/CDAbstractSharedMemoryMap.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "GeneralUtils.h"
 | 
			
		||||
 | 
			
		||||
#include "Game.h"
 | 
			
		||||
#include "dLogger.h"
 | 
			
		||||
#include "dServer.h"
 | 
			
		||||
 | 
			
		||||
#include "CDTable.h"
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractProvider.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/interprocess/managed_shared_memory.hpp>
 | 
			
		||||
#include <boost/interprocess/containers/map.hpp>
 | 
			
		||||
#include <boost/interprocess/allocators/allocator.hpp>
 | 
			
		||||
#include <boost/interprocess/containers/string.hpp>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
 | 
			
		||||
template <
 | 
			
		||||
    typename KeyType,
 | 
			
		||||
    typename MappedType
 | 
			
		||||
>
 | 
			
		||||
class CDAbstractSharedMemoryMap : public CDAbstractProvider<KeyType, MappedType>
 | 
			
		||||
{
 | 
			
		||||
    typedef std::pair<const KeyType, MappedType> ValueType;
 | 
			
		||||
 | 
			
		||||
    typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
 | 
			
		||||
 | 
			
		||||
    typedef boost::interprocess::map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> Map;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::map<KeyType, MappedType> m_CacheMap;
 | 
			
		||||
 | 
			
		||||
    std::string m_Name;
 | 
			
		||||
 | 
			
		||||
    size_t m_Size;
 | 
			
		||||
 | 
			
		||||
    bool m_Host;
 | 
			
		||||
    Map* m_HostEntries;
 | 
			
		||||
 | 
			
		||||
    boost::interprocess::managed_shared_memory m_ClientSegment;
 | 
			
		||||
    ShmemAllocator* m_ClientAllocInst;
 | 
			
		||||
    boost::interprocess::offset_ptr<Map> m_ClientEntires;
 | 
			
		||||
 | 
			
		||||
    CDAbstractSharedMemoryMap(std::string name, size_t size)
 | 
			
		||||
    {
 | 
			
		||||
        m_Name = name;
 | 
			
		||||
        m_Size = size;
 | 
			
		||||
        m_Host = false;
 | 
			
		||||
        m_HostEntries = nullptr;
 | 
			
		||||
        m_ClientAllocInst = nullptr;
 | 
			
		||||
        m_ClientEntires = nullptr;
 | 
			
		||||
 | 
			
		||||
        LoadClient();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) override {
 | 
			
		||||
        const auto& cacheIt = m_CacheMap.find(key);
 | 
			
		||||
        if (cacheIt != m_CacheMap.end()) {
 | 
			
		||||
            return cacheIt->second;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto& it = m_ClientEntires->find(key);
 | 
			
		||||
        if (it == m_ClientEntires->end()) {
 | 
			
		||||
            return defaultValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return it->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const void SetEntry(const KeyType& key, const MappedType& value) {
 | 
			
		||||
        if (m_Host) {
 | 
			
		||||
            // If we are already hosting, we cannot add to the map, throw an error
 | 
			
		||||
            throw std::runtime_error("Can not add to a map that is already being hosted");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_CacheMap.emplace(key, value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadClient() override {
 | 
			
		||||
        try {
 | 
			
		||||
            m_ClientSegment = boost::interprocess::managed_shared_memory(boost::interprocess::open_read_only, m_Name.c_str());
 | 
			
		||||
 | 
			
		||||
            m_ClientAllocInst = new ShmemAllocator(m_ClientSegment.get_segment_manager());
 | 
			
		||||
 | 
			
		||||
            m_ClientEntires = m_ClientSegment.find<Map>(m_Name.c_str()).first;
 | 
			
		||||
 | 
			
		||||
            if (m_ClientEntires == nullptr) {
 | 
			
		||||
                throw std::runtime_error("Could not find shared memory segment " + m_Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (std::exception &e) {
 | 
			
		||||
            // Not open
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadHost() override {
 | 
			
		||||
        try {
 | 
			
		||||
            boost::interprocess::shared_memory_object::remove(m_Name.c_str());
 | 
			
		||||
 | 
			
		||||
            boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, m_Name.c_str(), m_Size);
 | 
			
		||||
 | 
			
		||||
            ShmemAllocator alloc(segment.get_segment_manager());
 | 
			
		||||
 | 
			
		||||
            m_HostEntries = segment.construct<Map>(m_Name.c_str()) (std::less<KeyType>(), alloc);
 | 
			
		||||
 | 
			
		||||
            // Copy cache
 | 
			
		||||
            for (const auto& pair : m_CacheMap) {
 | 
			
		||||
                m_HostEntries->insert(std::make_pair(pair.first, pair.second));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            m_Host = true;
 | 
			
		||||
 | 
			
		||||
            LoadClient();
 | 
			
		||||
        } catch (std::exception &e) {
 | 
			
		||||
            // Make sure the smemory is removed
 | 
			
		||||
            boost::interprocess::shared_memory_object::remove(m_Name.c_str());
 | 
			
		||||
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										150
									
								
								dDatabase/CDAbstractSharedMemoryProvider.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								dDatabase/CDAbstractSharedMemoryProvider.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractProvider.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/interprocess/managed_shared_memory.hpp>
 | 
			
		||||
#include <boost/interprocess/containers/map.hpp>
 | 
			
		||||
#include <boost/interprocess/allocators/allocator.hpp>
 | 
			
		||||
#include <boost/interprocess/containers/string.hpp>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
template <
 | 
			
		||||
    typename KeyType,
 | 
			
		||||
    typename MappedType
 | 
			
		||||
>
 | 
			
		||||
class CDAbstractSharedMemoryProvider : public CDAbstractProvider<KeyType, MappedType>
 | 
			
		||||
{
 | 
			
		||||
    typedef std::pair<const KeyType, MappedType> ValueType;
 | 
			
		||||
 | 
			
		||||
    typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
 | 
			
		||||
 | 
			
		||||
    typedef boost::interprocess::map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> Map;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::string m_Name;
 | 
			
		||||
    std::string m_MapName;
 | 
			
		||||
    std::function <ValueType(CppSQLite3Query&)> m_ParseEntry;
 | 
			
		||||
    std::function <int32_t(int32_t)> m_CalculateSize;
 | 
			
		||||
 | 
			
		||||
    bool m_Cache;
 | 
			
		||||
 | 
			
		||||
    std::unordered_map<KeyType, MappedType> m_CacheMap;
 | 
			
		||||
    
 | 
			
		||||
    bool m_Host;
 | 
			
		||||
    Map* m_HostEntries;
 | 
			
		||||
 | 
			
		||||
    boost::interprocess::managed_shared_memory m_ClientSegment;
 | 
			
		||||
    ShmemAllocator* m_ClientAllocInst;
 | 
			
		||||
    boost::interprocess::offset_ptr<Map> m_ClientEntires;
 | 
			
		||||
 | 
			
		||||
    CDAbstractSharedMemoryProvider(std::string name, std::function <ValueType(CppSQLite3Query&)> parseEntry, std::function <int32_t(int32_t)> calculateSize, bool cache)
 | 
			
		||||
    {
 | 
			
		||||
        m_Name = name;
 | 
			
		||||
        m_MapName = name + "Map";
 | 
			
		||||
        m_ParseEntry = parseEntry;
 | 
			
		||||
        m_CalculateSize = calculateSize;
 | 
			
		||||
        m_Cache = cache;
 | 
			
		||||
        m_Host = false;
 | 
			
		||||
        m_HostEntries = nullptr;
 | 
			
		||||
 | 
			
		||||
        LoadClient();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) override {
 | 
			
		||||
        if (m_Host) {
 | 
			
		||||
            auto it = m_HostEntries->find(key);
 | 
			
		||||
            if (it == m_HostEntries->end())
 | 
			
		||||
            {
 | 
			
		||||
                return defaultValue;
 | 
			
		||||
            }
 | 
			
		||||
            return it->second;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (m_Cache) {
 | 
			
		||||
            auto it = m_CacheMap.find(key);
 | 
			
		||||
            if (it != m_CacheMap.end()) {
 | 
			
		||||
                return it->second;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto& it = m_ClientEntires->find(key);
 | 
			
		||||
        if (it == m_ClientEntires->end())
 | 
			
		||||
        {
 | 
			
		||||
            if (m_Cache) {
 | 
			
		||||
                m_CacheMap.emplace(key, defaultValue);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return defaultValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (m_Cache) {
 | 
			
		||||
            m_CacheMap.emplace(key, it->second);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return it->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadClient() override {
 | 
			
		||||
        try {
 | 
			
		||||
            m_ClientSegment = boost::interprocess::managed_shared_memory(boost::interprocess::open_read_only, m_MapName.c_str());
 | 
			
		||||
 | 
			
		||||
            m_ClientAllocInst = new ShmemAllocator(m_ClientSegment.get_segment_manager());
 | 
			
		||||
 | 
			
		||||
            m_ClientEntires = m_ClientSegment.find<Map>(m_Name.c_str()).first;
 | 
			
		||||
 | 
			
		||||
            if (m_ClientEntires == nullptr) {
 | 
			
		||||
                throw std::runtime_error("Could not find shared memory segment " + m_Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (boost::interprocess::interprocess_exception& e) {
 | 
			
		||||
            // Not open
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadHost() override {
 | 
			
		||||
        try {
 | 
			
		||||
            boost::interprocess::shared_memory_object::remove(m_MapName.c_str());
 | 
			
		||||
 | 
			
		||||
            auto sizeQuery = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM " + m_Name);
 | 
			
		||||
 | 
			
		||||
            if (sizeQuery.eof()) {
 | 
			
		||||
                throw std::runtime_error("Could not get size of table " + m_Name);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int32_t size = sizeQuery.getIntField(0);
 | 
			
		||||
 | 
			
		||||
            size = m_CalculateSize(size);
 | 
			
		||||
 | 
			
		||||
            boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, m_MapName.c_str(), size);
 | 
			
		||||
 | 
			
		||||
            ShmemAllocator alloc_inst (segment.get_segment_manager());
 | 
			
		||||
 | 
			
		||||
            m_HostEntries = segment.construct<Map>(m_Name.c_str()) (std::less<KeyType>(), alloc_inst);
 | 
			
		||||
 | 
			
		||||
            auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM " + m_Name);
 | 
			
		||||
 | 
			
		||||
            while (!tableData.eof()) {
 | 
			
		||||
                ValueType entry = m_ParseEntry(tableData);
 | 
			
		||||
 | 
			
		||||
                m_HostEntries->insert(entry);
 | 
			
		||||
 | 
			
		||||
                tableData.nextRow();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            tableData.finalize();
 | 
			
		||||
 | 
			
		||||
            m_Host = true;
 | 
			
		||||
 | 
			
		||||
            LoadClient();
 | 
			
		||||
        } catch (std::exception &e) {
 | 
			
		||||
            // Make sure the smemory is removed
 | 
			
		||||
            boost::interprocess::shared_memory_object::remove(m_MapName.c_str());
 | 
			
		||||
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										74
									
								
								dDatabase/CDAbstractSqliteProvider.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								dDatabase/CDAbstractSqliteProvider.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "GeneralUtils.h"
 | 
			
		||||
 | 
			
		||||
#include "Game.h"
 | 
			
		||||
#include "dLogger.h"
 | 
			
		||||
#include "dServer.h"
 | 
			
		||||
 | 
			
		||||
#include "CDTable.h"
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractProvider.h"
 | 
			
		||||
 | 
			
		||||
template <
 | 
			
		||||
    typename KeyType,
 | 
			
		||||
    typename MappedType
 | 
			
		||||
>
 | 
			
		||||
class CDAbstractSqliteProvider : public CDAbstractProvider<KeyType, MappedType>
 | 
			
		||||
{
 | 
			
		||||
    typedef std::pair<const KeyType, MappedType> ValueType;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::string m_Name;
 | 
			
		||||
    std::function <ValueType(CppSQLite3Query&)> m_ParseEntry;
 | 
			
		||||
 | 
			
		||||
    std::unordered_map<KeyType, MappedType> m_Entries;
 | 
			
		||||
 | 
			
		||||
    CDAbstractSqliteProvider(std::string name, std::function <ValueType(CppSQLite3Query&)> parseEntry, bool cache)
 | 
			
		||||
    {
 | 
			
		||||
        m_Name = name;
 | 
			
		||||
        m_ParseEntry = parseEntry;
 | 
			
		||||
 | 
			
		||||
        LoadClient();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadClient() override {
 | 
			
		||||
        // First, get the size of the table
 | 
			
		||||
        uint32_t size = 0;
 | 
			
		||||
        auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM " + m_Name);
 | 
			
		||||
        while (!tableSize.eof()) {
 | 
			
		||||
            size = tableSize.getIntField(0, 0);
 | 
			
		||||
 | 
			
		||||
            tableSize.nextRow();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tableSize.finalize();
 | 
			
		||||
 | 
			
		||||
        // Reserve the size
 | 
			
		||||
        m_Entries.reserve(size);
 | 
			
		||||
 | 
			
		||||
        // Now get the data
 | 
			
		||||
        auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM " + m_Name);
 | 
			
		||||
        while (!tableData.eof()) {
 | 
			
		||||
            auto entry = m_ParseEntry(tableData);
 | 
			
		||||
 | 
			
		||||
            m_Entries.insert(entry);
 | 
			
		||||
 | 
			
		||||
            tableData.nextRow();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tableData.finalize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadHost() override {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const MappedType& GetEntry(const KeyType& key, const MappedType& defaultValue) override {
 | 
			
		||||
        auto it = m_Entries.find(key);
 | 
			
		||||
        if (it != m_Entries.end()) {
 | 
			
		||||
            return it->second;
 | 
			
		||||
        }
 | 
			
		||||
        return defaultValue;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -5,6 +5,8 @@ CDClientManager * CDClientManager::m_Address = nullptr;
 | 
			
		||||
 | 
			
		||||
//! Initializes the manager
 | 
			
		||||
void CDClientManager::Initialize(void) {
 | 
			
		||||
	CDTable::Initalize();
 | 
			
		||||
	
 | 
			
		||||
	tables.insert(std::make_pair("ActivityRewards", new CDActivityRewardsTable()));
 | 
			
		||||
	UNUSED(tables.insert(std::make_pair("Animations", new CDAnimationsTable())));
 | 
			
		||||
	tables.insert(std::make_pair("BehaviorParameter", new CDBehaviorParameterTable()));
 | 
			
		||||
@@ -44,3 +46,11 @@ void CDClientManager::Initialize(void) {
 | 
			
		||||
	tables.insert(std::make_pair("FeatureGating", new CDFeatureGatingTable()));
 | 
			
		||||
	tables.insert(std::make_pair("RailActivatorComponent", new CDRailActivatorComponentTable()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CDClientManager::LoadHost() {
 | 
			
		||||
	for (auto itr = this->tables.begin(); itr != this->tables.end(); ++itr) {
 | 
			
		||||
		itr->second->LoadHost();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CDTable::InitalizeHost();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -93,4 +93,6 @@ public:
 | 
			
		||||
        
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadHost();
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								dDatabase/CDProvider.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								dDatabase/CDProvider.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractProvider.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shared memory provider with CDAbstractSharedMemoryProvider<key, value>
 | 
			
		||||
 * 
 | 
			
		||||
 * Depends on the boost::interprocess library — header only
 | 
			
		||||
 * 
 | 
			
		||||
 * Requires that CD_PROVIDER_MEMORY is defined and CD_PROVIDER_SQLITE is not defined
 | 
			
		||||
 */
 | 
			
		||||
#if defined(CD_PROVIDER_MEMORY) && !defined(CD_PROVIDER_SQLITE)
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractSharedMemoryProvider.h"
 | 
			
		||||
 | 
			
		||||
#define CD_PROVIDER(provider, key, value) CDAbstractSharedMemoryProvider<key, value>* provider; typedef key CD_KEY; typedef value CD_VALUE
 | 
			
		||||
#define NEW_CD_PROVIDER(provider, name, parser, size_calculator, cache) provider = new CDAbstractSharedMemoryProvider<CD_KEY, CD_VALUE>(name, parser, size_calculator, cache)
 | 
			
		||||
 | 
			
		||||
template<typename KeyType, typename MappedType>
 | 
			
		||||
using CDProvider = CDAbstractSharedMemoryProvider<KeyType, MappedType>;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SQLite provider with CDAbstractSqliteProvider<key, value>
 | 
			
		||||
 * 
 | 
			
		||||
 * No extra dependencies
 | 
			
		||||
 * 
 | 
			
		||||
 * Requires that CD_PROVIDER_SQLITE or CD_PROVIDER_MEMORY is not defined — the default option
 | 
			
		||||
 */
 | 
			
		||||
#if defined(CD_PROVIDER_SQLITE) || !defined(CD_PROVIDER_MEMORY)
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractSqliteProvider.h"
 | 
			
		||||
 | 
			
		||||
#define CD_PROVIDER(provider, key, value) CDAbstractSqliteProvider<key, value>* provider; typedef key CD_KEY; typedef value CD_VALUE
 | 
			
		||||
#define NEW_CD_PROVIDER(provider, name, parser, size_calculator, cache) provider = new CDAbstractSqliteProvider<CD_KEY, CD_VALUE>(name, parser, cache)
 | 
			
		||||
 | 
			
		||||
template<typename KeyType, typename MappedType>
 | 
			
		||||
using CDProvider = CDAbstractSqliteProvider<KeyType, MappedType>;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -5,47 +5,27 @@
 | 
			
		||||
#include "dLogger.h"
 | 
			
		||||
#include "dServer.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/interprocess/managed_shared_memory.hpp>
 | 
			
		||||
#include <boost/interprocess/containers/map.hpp>
 | 
			
		||||
#include <boost/interprocess/allocators/allocator.hpp>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include "CDProvider.h"
 | 
			
		||||
 | 
			
		||||
typedef size_t    KeyType;
 | 
			
		||||
typedef float  MappedType;
 | 
			
		||||
typedef std::pair<const KeyType, MappedType> ValueType;
 | 
			
		||||
 | 
			
		||||
typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
 | 
			
		||||
 | 
			
		||||
typedef boost::interprocess::map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> CDBehaviorParameterMap;
 | 
			
		||||
 | 
			
		||||
CDBehaviorParameterMap *table = nullptr;
 | 
			
		||||
 | 
			
		||||
boost::interprocess::managed_shared_memory segment;
 | 
			
		||||
ShmemAllocator* alloc_inst;
 | 
			
		||||
boost::interprocess::offset_ptr<CDBehaviorParameterMap> m;
 | 
			
		||||
CD_PROVIDER(BehaviorParameterProvider, size_t, float);
 | 
			
		||||
 | 
			
		||||
//! Constructor
 | 
			
		||||
CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
 | 
			
		||||
	try {
 | 
			
		||||
		segment = boost::interprocess::managed_shared_memory(boost::interprocess::open_read_only, "CDBehaviorParameterTable");
 | 
			
		||||
	NEW_CD_PROVIDER(BehaviorParameterProvider, "BehaviorParameter", [](CppSQLite3Query& query) {
 | 
			
		||||
		size_t hash = 0;
 | 
			
		||||
 | 
			
		||||
		alloc_inst = new ShmemAllocator(segment.get_segment_manager());
 | 
			
		||||
		int32_t behaviorID = query.getIntField(0, -1);
 | 
			
		||||
		std::string parameterID = query.getStringField(1, "");
 | 
			
		||||
		
 | 
			
		||||
		GeneralUtils::hash_combine(hash, behaviorID);
 | 
			
		||||
		GeneralUtils::hash_combine(hash, parameterID);
 | 
			
		||||
 | 
			
		||||
		m = segment.find<CDBehaviorParameterMap>("CDBehaviorParameter").first;
 | 
			
		||||
		float value = query.getFloatField(2, -1.0f);
 | 
			
		||||
 | 
			
		||||
		if (m == nullptr) {
 | 
			
		||||
			Game::logger->Log("CDBehaviorParameterTable", "CDBehaviorParameter segment is nullptr!\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Load the entire table into m_Entries
 | 
			
		||||
		/*for (auto it = m->begin(); it != m->end(); ++it) {
 | 
			
		||||
			m_Entries.insert(std::make_pair(it->first, it->second));
 | 
			
		||||
		}*/
 | 
			
		||||
	} catch (std::exception &e) {
 | 
			
		||||
		// Not open, we are master
 | 
			
		||||
	}
 | 
			
		||||
		return std::make_pair(hash, value);
 | 
			
		||||
	}, [](int32_t size) {
 | 
			
		||||
		return 40 * 1000 * 1000;
 | 
			
		||||
	}, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Destructor
 | 
			
		||||
@@ -62,95 +42,10 @@ float CDBehaviorParameterTable::GetEntry(const uint32_t behaviorID, const std::s
 | 
			
		||||
	GeneralUtils::hash_combine(hash, behaviorID);
 | 
			
		||||
	GeneralUtils::hash_combine(hash, name);
 | 
			
		||||
 | 
			
		||||
	// Search for specific parameter
 | 
			
		||||
	try {
 | 
			
		||||
		/*boost::interprocess::managed_shared_memory segment(boost::interprocess::open_read_only, "CDBehaviorParameterTable");
 | 
			
		||||
 | 
			
		||||
		// If the segment manager is not null, then the segment exists
 | 
			
		||||
		// Get the table from the segment
 | 
			
		||||
		ShmemAllocator alloc_inst (segment.get_segment_manager());
 | 
			
		||||
 | 
			
		||||
		boost::interprocess::offset_ptr<CDBehaviorParameterMap> m = segment.find<CDBehaviorParameterMap>("CDBehaviorParameter").first;
 | 
			
		||||
 | 
			
		||||
		if (m == nullptr) {
 | 
			
		||||
			Game::logger->Log("CDBehaviorParameterTable", "CDBehaviorParameter segment is nullptr!\n");
 | 
			
		||||
 | 
			
		||||
			return defaultValue;
 | 
			
		||||
		}*/
 | 
			
		||||
 | 
			
		||||
		// Start a timer
 | 
			
		||||
		auto start = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
		auto it = m->find(hash);
 | 
			
		||||
 | 
			
		||||
		bool found = it != m->end();
 | 
			
		||||
 | 
			
		||||
		// End the timer
 | 
			
		||||
		auto end = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
		// Get duraction
 | 
			
		||||
		auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
 | 
			
		||||
		
 | 
			
		||||
		// Reset the timer
 | 
			
		||||
		/*start = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
		auto nativeIt = m_Entries.find(hash);
 | 
			
		||||
 | 
			
		||||
		bool nativeFound = nativeIt != m_Entries.end();
 | 
			
		||||
 | 
			
		||||
		// End the timer
 | 
			
		||||
		end = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
		// Get duraction
 | 
			
		||||
		auto nativeDuration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);*/
 | 
			
		||||
 | 
			
		||||
		//Game::logger->Log("CDBehaviorParameterTable", "Duration: (sm) %fms / (m) %fms -> %f\n", duration.count() / 1000000.0f, nativeDuration.count() / 1000000.0f, (double) duration.count() / (double) nativeDuration.count());
 | 
			
		||||
 | 
			
		||||
		if (found) {
 | 
			
		||||
			return it->second;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return defaultValue;
 | 
			
		||||
	}
 | 
			
		||||
	catch (std::exception &e) {
 | 
			
		||||
		Game::logger->Log("CDBehaviorParameterTable", "Failed to find entry for behaviorID: %d, parameterID: %s\n%e\n", behaviorID, name.c_str(), e.what());
 | 
			
		||||
 | 
			
		||||
		return defaultValue;
 | 
			
		||||
	}
 | 
			
		||||
	return BehaviorParameterProvider->GetEntry(hash, defaultValue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CDBehaviorParameterTable::CreateSharedMap()
 | 
			
		||||
void CDBehaviorParameterTable::LoadHost()
 | 
			
		||||
{
 | 
			
		||||
	boost::interprocess::shared_memory_object::remove("CDBehaviorParameterTable");
 | 
			
		||||
 | 
			
		||||
	Game::logger->Log("CDBehaviorParameterTable", "Create shared memory segment.\n");
 | 
			
		||||
 | 
			
		||||
	// Create the segment, TODO: calculate size
 | 
			
		||||
	boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, "CDBehaviorParameterTable", 40 * 1000 * 1000);
 | 
			
		||||
 | 
			
		||||
	ShmemAllocator alloc_inst (segment.get_segment_manager());
 | 
			
		||||
 | 
			
		||||
	table = segment.construct<CDBehaviorParameterMap>("CDBehaviorParameter") (std::less<KeyType>(), alloc_inst);
 | 
			
		||||
 | 
			
		||||
	auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
 | 
			
		||||
 | 
			
		||||
	size_t hash = 0;
 | 
			
		||||
 | 
			
		||||
	while (!tableData.eof()) {
 | 
			
		||||
		hash = 0;
 | 
			
		||||
 | 
			
		||||
		int32_t behaviorID = tableData.getIntField(0, -1);
 | 
			
		||||
		std::string parameterID = tableData.getStringField(1, "");
 | 
			
		||||
		
 | 
			
		||||
		GeneralUtils::hash_combine(hash, behaviorID);
 | 
			
		||||
		GeneralUtils::hash_combine(hash, parameterID);
 | 
			
		||||
 | 
			
		||||
		float value = tableData.getFloatField(2, -1.0f);
 | 
			
		||||
 | 
			
		||||
		table->insert(ValueType(hash, value));
 | 
			
		||||
 | 
			
		||||
		tableData.nextRow();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tableData.finalize();
 | 
			
		||||
	BehaviorParameterProvider->LoadHost();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,8 @@ struct CDBehaviorParameter {
 | 
			
		||||
 | 
			
		||||
//! BehaviorParameter table
 | 
			
		||||
class CDBehaviorParameterTable : public CDTable {
 | 
			
		||||
private:
 | 
			
		||||
	std::unordered_map<size_t, float> m_Entries;
 | 
			
		||||
public:
 | 
			
		||||
    static void CreateSharedMap();
 | 
			
		||||
    void LoadHost() override;
 | 
			
		||||
    
 | 
			
		||||
    //! Constructor
 | 
			
		||||
    CDBehaviorParameterTable(void);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,25 @@
 | 
			
		||||
#include "CDBehaviorTemplateTable.h"
 | 
			
		||||
 | 
			
		||||
#include "CDProvider.h"
 | 
			
		||||
 | 
			
		||||
CDBehaviorTemplate EmptyBehaviorTemplate {0, 0, 0, 0};
 | 
			
		||||
 | 
			
		||||
CD_PROVIDER(BehaviorTemplateProvider, uint32_t, CDBehaviorTemplate);
 | 
			
		||||
 | 
			
		||||
//! Constructor
 | 
			
		||||
CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) {
 | 
			
		||||
    
 | 
			
		||||
    // First, get the size of the table
 | 
			
		||||
    unsigned int size = 0;
 | 
			
		||||
    auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM BehaviorTemplate");
 | 
			
		||||
    while (!tableSize.eof()) {
 | 
			
		||||
        size = tableSize.getIntField(0, 0);
 | 
			
		||||
        
 | 
			
		||||
        tableSize.nextRow();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
	tableSize.finalize();
 | 
			
		||||
    
 | 
			
		||||
    // Reserve the size
 | 
			
		||||
    this->entries.reserve(size);
 | 
			
		||||
 | 
			
		||||
    // Now get the data
 | 
			
		||||
    auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorTemplate");
 | 
			
		||||
    while (!tableData.eof()) {
 | 
			
		||||
    NEW_CD_PROVIDER(BehaviorTemplateProvider, "BehaviorTemplate", [](CppSQLite3Query& query) {
 | 
			
		||||
        CDBehaviorTemplate entry;
 | 
			
		||||
        entry.behaviorID = tableData.getIntField(0, -1);
 | 
			
		||||
        entry.templateID = tableData.getIntField(1, -1);
 | 
			
		||||
        entry.effectID = tableData.getIntField(2, -1);
 | 
			
		||||
        auto candidateToAdd = tableData.getStringField(3, "");
 | 
			
		||||
        auto parameter = m_EffectHandles.find(candidateToAdd);
 | 
			
		||||
        if (parameter != m_EffectHandles.end()) {
 | 
			
		||||
            entry.effectHandle = parameter;
 | 
			
		||||
        } else {
 | 
			
		||||
            entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        this->entries.push_back(entry);
 | 
			
		||||
        this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry));
 | 
			
		||||
        tableData.nextRow();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	tableData.finalize();
 | 
			
		||||
        entry.behaviorID = query.getIntField(0, -1);
 | 
			
		||||
        entry.templateID = query.getIntField(1, -1);
 | 
			
		||||
        entry.effectID = query.getIntField(2, -1);
 | 
			
		||||
        entry.effectHandle = CDTable::SetString(query.getStringField(3, ""));
 | 
			
		||||
        
 | 
			
		||||
        return std::make_pair(entry.behaviorID, entry);
 | 
			
		||||
    }, [](int32_t size) {
 | 
			
		||||
        return 40 * 1000 * 1000;
 | 
			
		||||
    }, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Destructor
 | 
			
		||||
@@ -48,30 +30,10 @@ std::string CDBehaviorTemplateTable::GetName(void) const {
 | 
			
		||||
    return "BehaviorTemplate";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Queries the table with a custom "where" clause
 | 
			
		||||
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<bool(CDBehaviorTemplate)> predicate) {
 | 
			
		||||
    
 | 
			
		||||
    std::vector<CDBehaviorTemplate> data = cpplinq::from(this->entries)
 | 
			
		||||
    >> cpplinq::where(predicate)
 | 
			
		||||
    >> cpplinq::to_vector();
 | 
			
		||||
    
 | 
			
		||||
    return data;
 | 
			
		||||
const CDBehaviorTemplate& CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) const {
 | 
			
		||||
    return BehaviorTemplateProvider->GetEntry(behaviorID, EmptyBehaviorTemplate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Gets all the entries in the table
 | 
			
		||||
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::GetEntries(void) const {
 | 
			
		||||
    return this->entries;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) {
 | 
			
		||||
    auto entry = this->entriesMappedByBehaviorID.find(behaviorID);
 | 
			
		||||
    if (entry == this->entriesMappedByBehaviorID.end()) {
 | 
			
		||||
        CDBehaviorTemplate entryToReturn;
 | 
			
		||||
        entryToReturn.behaviorID = 0;
 | 
			
		||||
        entryToReturn.effectHandle = m_EffectHandles.end();
 | 
			
		||||
        entryToReturn.effectID = 0;
 | 
			
		||||
        return entryToReturn;
 | 
			
		||||
    } else {
 | 
			
		||||
        return entry->second;
 | 
			
		||||
    }
 | 
			
		||||
void CDBehaviorTemplateTable::LoadHost() {
 | 
			
		||||
    BehaviorTemplateProvider->LoadHost();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,17 +15,14 @@ struct CDBehaviorTemplate {
 | 
			
		||||
    unsigned int behaviorID;                                         //!< The Behavior ID
 | 
			
		||||
    unsigned int templateID;                                         //!< The Template ID (LOT)
 | 
			
		||||
    unsigned int effectID;                                           //!< The Effect ID attached
 | 
			
		||||
    std::unordered_set<std::string>::iterator effectHandle;          //!< The effect handle
 | 
			
		||||
    size_t effectHandle;                                             //!< The effect handle
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//! BehaviorTemplate table
 | 
			
		||||
class CDBehaviorTemplateTable : public CDTable {
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<CDBehaviorTemplate> entries;
 | 
			
		||||
    std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
 | 
			
		||||
    std::unordered_set<std::string> m_EffectHandles;
 | 
			
		||||
public:
 | 
			
		||||
    void LoadHost() override;
 | 
			
		||||
    
 | 
			
		||||
    //! Constructor
 | 
			
		||||
    CDBehaviorTemplateTable(void);
 | 
			
		||||
@@ -39,17 +36,5 @@ public:
 | 
			
		||||
     */
 | 
			
		||||
    std::string GetName(void) const override;
 | 
			
		||||
    
 | 
			
		||||
    //! Queries the table with a custom "where" clause
 | 
			
		||||
    /*!
 | 
			
		||||
      \param predicate The predicate
 | 
			
		||||
     */
 | 
			
		||||
    std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
 | 
			
		||||
    
 | 
			
		||||
    //! Gets all the entries in the table
 | 
			
		||||
    /*!
 | 
			
		||||
       \return The entries
 | 
			
		||||
     */
 | 
			
		||||
    std::vector<CDBehaviorTemplate> GetEntries(void) const;
 | 
			
		||||
 | 
			
		||||
    const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
 | 
			
		||||
    const CDBehaviorTemplate& GetByBehaviorID(const uint32_t behaviorID) const;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,58 +1,30 @@
 | 
			
		||||
 | 
			
		||||
#include "CDComponentsRegistryTable.h"
 | 
			
		||||
 | 
			
		||||
#define CDCLIENT_CACHE_ALL
 | 
			
		||||
 | 
			
		||||
#include "CDProvider.h"
 | 
			
		||||
 | 
			
		||||
CD_PROVIDER(ComponentsRegistryProvider, size_t, int32_t);
 | 
			
		||||
 | 
			
		||||
//! Constructor
 | 
			
		||||
CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
 | 
			
		||||
    
 | 
			
		||||
#ifdef CDCLIENT_CACHE_ALL
 | 
			
		||||
    // First, get the size of the table
 | 
			
		||||
    unsigned int size = 0;
 | 
			
		||||
    auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ComponentsRegistry");
 | 
			
		||||
    while (!tableSize.eof()) {
 | 
			
		||||
        size = tableSize.getIntField(0, 0);
 | 
			
		||||
        
 | 
			
		||||
        tableSize.nextRow();
 | 
			
		||||
    }
 | 
			
		||||
        
 | 
			
		||||
	tableSize.finalize();
 | 
			
		||||
    
 | 
			
		||||
    // Reserve the size
 | 
			
		||||
    //this->entries.reserve(size);
 | 
			
		||||
    
 | 
			
		||||
    // Now get the data
 | 
			
		||||
    auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
 | 
			
		||||
    while (!tableData.eof()) {
 | 
			
		||||
        CDComponentsRegistry entry;
 | 
			
		||||
        entry.id = tableData.getIntField(0, -1);
 | 
			
		||||
        entry.component_type = tableData.getIntField(1, -1);
 | 
			
		||||
        entry.component_id = tableData.getIntField(2, -1);
 | 
			
		||||
 | 
			
		||||
		this->mappedEntries.insert_or_assign(((uint64_t) entry.component_type) << 32 | ((uint64_t) entry.id), entry.component_id);
 | 
			
		||||
        
 | 
			
		||||
        //this->entries.push_back(entry);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		//Darwin's stuff:
 | 
			
		||||
		const auto& it = this->mappedEntries.find(entry.id);
 | 
			
		||||
		if (it != mappedEntries.end()) {
 | 
			
		||||
			const auto& iter = it->second.find(entry.component_type);
 | 
			
		||||
			if (iter == it->second.end()) {
 | 
			
		||||
				it->second.insert(std::make_pair(entry.component_type, entry.component_id));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			std::map<unsigned int, unsigned int> map;
 | 
			
		||||
			map.insert(std::make_pair(entry.component_type, entry.component_id));
 | 
			
		||||
			this->mappedEntries.insert(std::make_pair(entry.id, map));
 | 
			
		||||
		}
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
        tableData.nextRow();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	tableData.finalize();
 | 
			
		||||
#endif
 | 
			
		||||
	NEW_CD_PROVIDER(ComponentsRegistryProvider, "ComponentsRegistry", [](CppSQLite3Query& query) {
 | 
			
		||||
		size_t hash = 0;
 | 
			
		||||
		
 | 
			
		||||
		int32_t componentID = query.getIntField(0, -1);
 | 
			
		||||
		int32_t componentType = query.getIntField(1, -1);
 | 
			
		||||
		
 | 
			
		||||
		hash = componentID;
 | 
			
		||||
		hash = hash << 32;
 | 
			
		||||
		hash |= componentType;
 | 
			
		||||
		
 | 
			
		||||
		int32_t componentHandle = query.getIntField(2, -1);
 | 
			
		||||
		
 | 
			
		||||
		return std::make_pair(hash, componentHandle);
 | 
			
		||||
	}, [](int32_t size) {
 | 
			
		||||
		return 10 * 1000 * 1000;
 | 
			
		||||
	}, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Destructor
 | 
			
		||||
@@ -63,69 +35,15 @@ std::string CDComponentsRegistryTable::GetName(void) const {
 | 
			
		||||
    return "ComponentsRegistry";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, uint32_t componentType, int32_t defaultValue) 
 | 
			
		||||
{
 | 
			
		||||
	const auto& iter = this->mappedEntries.find(((uint64_t) componentType) << 32 | ((uint64_t) id));
 | 
			
		||||
 | 
			
		||||
	if (iter == this->mappedEntries.end())
 | 
			
		||||
	{
 | 
			
		||||
		return defaultValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return iter->second;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	const auto& it = this->mappedEntries.find(id);
 | 
			
		||||
	if (it != mappedEntries.end()) {
 | 
			
		||||
		const auto& iter = it->second.find(componentType);
 | 
			
		||||
		if (iter != it->second.end()) {
 | 
			
		||||
			return iter->second;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
#ifndef CDCLIENT_CACHE_ALL
 | 
			
		||||
    // Now get the data
 | 
			
		||||
	std::stringstream query;
 | 
			
		||||
 | 
			
		||||
	query << "SELECT * FROM ComponentsRegistry WHERE id = " << std::to_string(id);
 | 
			
		||||
 | 
			
		||||
	auto tableData = CDClientDatabase::ExecuteQuery(query.str());
 | 
			
		||||
    while (!tableData.eof()) {
 | 
			
		||||
        CDComponentsRegistry entry;
 | 
			
		||||
        entry.id = tableData.getIntField(0, -1);
 | 
			
		||||
        entry.component_type = tableData.getIntField(1, -1);
 | 
			
		||||
        entry.component_id = tableData.getIntField(2, -1);
 | 
			
		||||
        
 | 
			
		||||
        //this->entries.push_back(entry);
 | 
			
		||||
 | 
			
		||||
		//Darwin's stuff:
 | 
			
		||||
		const auto& it = this->mappedEntries.find(entry.id);
 | 
			
		||||
		if (it != mappedEntries.end()) {
 | 
			
		||||
			const auto& iter = it->second.find(entry.component_type);
 | 
			
		||||
			if (iter == it->second.end()) {
 | 
			
		||||
				it->second.insert(std::make_pair(entry.component_type, entry.component_id));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			std::map<unsigned int, unsigned int> map;
 | 
			
		||||
			map.insert(std::make_pair(entry.component_type, entry.component_id));
 | 
			
		||||
			this->mappedEntries.insert(std::make_pair(entry.id, map));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        tableData.nextRow();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	tableData.finalize();
 | 
			
		||||
 | 
			
		||||
	const auto& it2 = this->mappedEntries.find(id);
 | 
			
		||||
	if (it2 != mappedEntries.end()) {
 | 
			
		||||
		const auto& iter = it2->second.find(componentType);
 | 
			
		||||
		if (iter != it2->second.end()) {
 | 
			
		||||
			return iter->second;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return defaultValue;
 | 
			
		||||
#endif
 | 
			
		||||
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, uint32_t componentType, int32_t defaultValue) {
 | 
			
		||||
	size_t hash = 0;
 | 
			
		||||
	hash = id;
 | 
			
		||||
	hash = hash << 32;
 | 
			
		||||
	hash |= componentType;
 | 
			
		||||
	
 | 
			
		||||
	return ComponentsRegistryProvider->GetEntry(hash, defaultValue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CDComponentsRegistryTable::LoadHost() {
 | 
			
		||||
	ComponentsRegistryProvider->LoadHost();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ private:
 | 
			
		||||
    std::map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
    void LoadHost() override;
 | 
			
		||||
    
 | 
			
		||||
    //! Constructor
 | 
			
		||||
    CDComponentsRegistryTable(void);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								dDatabase/Tables/CDTable.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								dDatabase/Tables/CDTable.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
#include "CDTable.h"
 | 
			
		||||
 | 
			
		||||
#if defined(CD_PROVIDER_MEMORY)
 | 
			
		||||
 | 
			
		||||
#include "CDAbstractSharedMemoryMap.h"
 | 
			
		||||
 | 
			
		||||
typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator; 
 | 
			
		||||
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> my_string;
 | 
			
		||||
 | 
			
		||||
CDAbstractSharedMemoryMap<size_t, boost::interprocess::string>* CDStringMap;
 | 
			
		||||
 | 
			
		||||
void CDTable::InitalizeHost()
 | 
			
		||||
{
 | 
			
		||||
    CDStringMap->LoadHost();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CDTable::Initalize()
 | 
			
		||||
{
 | 
			
		||||
    CDStringMap = new CDAbstractSharedMemoryMap<size_t, boost::interprocess::string>("CDStringMap", 10 * 1000 * 1000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string CDTable::GetString(size_t handle)
 | 
			
		||||
{
 | 
			
		||||
    std::string str = std::string(CDStringMap->GetEntry(handle, "").c_str());
 | 
			
		||||
 | 
			
		||||
    Game::logger->Log("CDTable", "GetString: %s\n", str.c_str());
 | 
			
		||||
 | 
			
		||||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t CDTable::SetString(std::string value)
 | 
			
		||||
{
 | 
			
		||||
    size_t hash = 0;
 | 
			
		||||
 | 
			
		||||
    GeneralUtils::hash_combine(hash, value);
 | 
			
		||||
 | 
			
		||||
    CDStringMap->SetEntry(hash, boost::interprocess::string(value.c_str()));
 | 
			
		||||
 | 
			
		||||
    return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
std::unordered_map<size_t, std::string> CDStringMap;
 | 
			
		||||
 | 
			
		||||
void CDTable::InitalizeHost()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CDTable::Initalize()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string CDTable::GetString(size_t handle)
 | 
			
		||||
{
 | 
			
		||||
    return CDStringMap[handle];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t CDTable::SetString(std::string value)
 | 
			
		||||
{
 | 
			
		||||
    size_t hash = 0;
 | 
			
		||||
 | 
			
		||||
    GeneralUtils::hash_combine(hash, value);
 | 
			
		||||
 | 
			
		||||
    CDStringMap[hash] = value;
 | 
			
		||||
 | 
			
		||||
    return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -38,4 +38,27 @@ public:
 | 
			
		||||
      \return The table name
 | 
			
		||||
     */
 | 
			
		||||
    virtual std::string GetName() const = 0;
 | 
			
		||||
 | 
			
		||||
    //! Loads the table into shared memory
 | 
			
		||||
    virtual void LoadHost() {};
 | 
			
		||||
 | 
			
		||||
    //! Initalizes the table services
 | 
			
		||||
    static void Initalize();
 | 
			
		||||
 | 
			
		||||
    //! Initalizes the table services as host
 | 
			
		||||
    static void InitalizeHost();
 | 
			
		||||
 | 
			
		||||
    //! Get a string from a handle
 | 
			
		||||
    /*!
 | 
			
		||||
      \param handle The handle to get the string from
 | 
			
		||||
      \return The string
 | 
			
		||||
     */
 | 
			
		||||
    static std::string GetString(size_t handle);
 | 
			
		||||
 | 
			
		||||
    //! Set a string
 | 
			
		||||
    /*!
 | 
			
		||||
      \param value The string to set
 | 
			
		||||
      \return The handle to the string
 | 
			
		||||
     */
 | 
			
		||||
    static size_t SetString(std::string value);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
set(DDATABASE_TABLES_SOURCES "CDActivitiesTable.cpp"
 | 
			
		||||
set(DDATABASE_TABLES_SOURCES "CDTable.cpp" "CDActivitiesTable.cpp"
 | 
			
		||||
	"CDActivityRewardsTable.cpp"
 | 
			
		||||
	"CDAnimationsTable.cpp"
 | 
			
		||||
	"CDBehaviorParameterTable.cpp"
 | 
			
		||||
 
 | 
			
		||||
@@ -445,7 +445,7 @@ Behavior::Behavior(const uint32_t behaviorId)
 | 
			
		||||
 | 
			
		||||
	this->m_effectId = templateInDatabase.effectID;
 | 
			
		||||
 | 
			
		||||
	this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
 | 
			
		||||
	this->m_effectHandle = new std::string(CDTable::GetString(templateInDatabase.effectHandle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1754,6 +1754,40 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
	if (chatCommand == "statm" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER)
 | 
			
		||||
	{
 | 
			
		||||
		// Print and format the output of /proc/self/statm
 | 
			
		||||
		std::ifstream statm("/proc/self/statm");
 | 
			
		||||
 | 
			
		||||
		if (!statm.is_open())
 | 
			
		||||
		{
 | 
			
		||||
			ChatPackets::SendSystemMessage(sysAddr, u"Failed to open /proc/self/statm");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Scan for the different fields
 | 
			
		||||
		uint64_t size, resident, share, text, lib, data, dirty;
 | 
			
		||||
		statm >> size >> resident >> share >> text >> lib >> data >> dirty;
 | 
			
		||||
 | 
			
		||||
		// Get the page size
 | 
			
		||||
		size_t pageSize = sysconf(_SC_PAGESIZE);
 | 
			
		||||
 | 
			
		||||
		// Print the output
 | 
			
		||||
		ChatPackets::SendSystemMessage(
 | 
			
		||||
			sysAddr,
 | 
			
		||||
			u"Size: " + GeneralUtils::to_u16string((float) ((double) size * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB\nResident: " + GeneralUtils::to_u16string((float) ((double) resident * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB\nShared: " + GeneralUtils::to_u16string((float) ((double) share * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB\nText: " + GeneralUtils::to_u16string((float) ((double) text * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB\nLibrary: " + GeneralUtils::to_u16string((float) ((double) lib * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB\nData: " + GeneralUtils::to_u16string((float) ((double) data * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB\nDirty: " + GeneralUtils::to_u16string((float) ((double) dirty * pageSize / 1.024e6)) +
 | 
			
		||||
			u"MB"
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (chatCommand == "rollloot" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && args.size() >= 3) {
 | 
			
		||||
		uint32_t lootMatrixIndex = 0;
 | 
			
		||||
		uint32_t targetLot = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -48,16 +48,28 @@ Instance * InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, L
 | 
			
		||||
 | 
			
		||||
    //Start the actual process:
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
	std::string cmd = "start ./WorldServer.exe -zone ";
 | 
			
		||||
	std::string cmd = "start ./WorldServer.exe";
 | 
			
		||||
#else
 | 
			
		||||
	std::string cmd;
 | 
			
		||||
    if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
 | 
			
		||||
		cmd = "sudo ./WorldServer -zone ";
 | 
			
		||||
 | 
			
		||||
	Game::logger->Log("InstanceManager", "world_command: %s\n", Game::config->GetValue("world_command").c_str());
 | 
			
		||||
 | 
			
		||||
	if (!Game::config->GetValue("world_command").empty()) {
 | 
			
		||||
		cmd = Game::config->GetValue("world_command");
 | 
			
		||||
		// Replace %map%_%instance%_%time% with the correct values
 | 
			
		||||
		cmd = cmd.replace(cmd.find("%map%"), 5, std::to_string(mapID));
 | 
			
		||||
		cmd = cmd.replace(cmd.find("%instance%"), 10, std::to_string(instance->GetInstanceID()));
 | 
			
		||||
		cmd = cmd.replace(cmd.find("%time%"), 5, std::to_string(time(nullptr)));
 | 
			
		||||
		// Remove any other %
 | 
			
		||||
		cmd = cmd.replace(cmd.find("%"), 1, "");
 | 
			
		||||
	} else if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
 | 
			
		||||
		cmd = "sudo ./WorldServer";
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "./WorldServer -zone ";
 | 
			
		||||
		cmd = "./WorldServer";
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    cmd.append(" -zone ");
 | 
			
		||||
    cmd.append(std::to_string(mapID));
 | 
			
		||||
    cmd.append(" -port ");
 | 
			
		||||
    cmd.append(std::to_string(port));
 | 
			
		||||
@@ -73,6 +85,8 @@ Instance * InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, L
 | 
			
		||||
    cmd.append("&"); //Sends our next process to the background on Linux
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	Game::logger->Log("InstanceManager", "Starting instance %i with command: %s\n", instance->GetInstanceID(), cmd.c_str());
 | 
			
		||||
 | 
			
		||||
    system(cmd.c_str());
 | 
			
		||||
 | 
			
		||||
    m_Instances.push_back(instance);
 | 
			
		||||
 
 | 
			
		||||
@@ -226,7 +226,7 @@ int main(int argc, char** argv) {
 | 
			
		||||
	ObjectIDManager::Instance()->Initialize(Game::logger);
 | 
			
		||||
	Game::im = new InstanceManager(Game::logger, Game::server->GetIP());
 | 
			
		||||
 | 
			
		||||
	CDBehaviorParameterTable::CreateSharedMap();
 | 
			
		||||
	CDClientManager::Instance()->LoadHost();
 | 
			
		||||
 | 
			
		||||
	//Depending on the config, start up servers:
 | 
			
		||||
	if (config.GetValue("prestart_servers") != "" && config.GetValue("prestart_servers") == "1") {
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ void AuthPackets::HandleHandshake(dServer* server, Packet* packet) {
 | 
			
		||||
void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, const std::string& nextServerIP, uint16_t nextServerPort) {
 | 
			
		||||
	RakNet::BitStream bitStream;
 | 
			
		||||
	PacketUtils::WriteHeader(bitStream, SERVER, MSG_SERVER_VERSION_CONFIRM);
 | 
			
		||||
	bitStream.Write<unsigned int>(NET_VERSION);	
 | 
			
		||||
	bitStream.Write<unsigned int>(171023);	
 | 
			
		||||
	bitStream.Write(uint32_t(0x93));
 | 
			
		||||
	
 | 
			
		||||
	if (nextServerPort == 1001) bitStream.Write(uint32_t(1)); //Conn: auth
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user