1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //#include "pd_string_manager.h"
24 //#include <nel/misc/file.h>
25 //#include <nel/misc/command.h>
26 //#include <nel/net/unified_network.h>
27 //#include <nel/net/service.h>
30 //#include "timestamp.h"
32 //using namespace std;
33 //using namespace NLMISC;
34 //using namespace NLNET;
43 ////void cbStoreStringResult(CMessage& msgin, const string &serviceName, uint16 serviceId);
45 ////TUnifiedCallbackItem PDStringManagerCbArray[] =
47 //// { "STORE_STRING_RESULT", cbStoreStringResult },
50 ////void cbStoreStringResult(CMessage& msgin, const string &serviceName, uint16 serviceId)
52 //// if (CPDStringManager::_NbProcessingStoreStringRequests)
54 //// CPDStringManager::_NbProcessingStoreStringRequests--;
57 //// nlwarning("<cbStoreStringResult> received more STORE_STRING_RESULT messages than sent STORE_STRING requests");
62 //// msgin.serial(str);
63 //// msgin.serial(stringId);
66 //// for (i=0; i<CPDSLib::_Libs.size(); ++i)
68 //// CPDSLib* lib = CPDSLib::_Libs[i];
70 //// lib->getStringManager().setStringId(str, stringId);
75 //// Is net callback ready?
76 //bool CPDStringManager::_InitCb = false;
79 //ucstring CPDStringManager::_NullStr;
81 ///// Number of store string requests that have not been processed by IOS yet
82 //uint CPDStringManager::_NbProcessingStoreStringRequests = 0;
88 //CPDStringManager::CPDStringManager()
98 //CPDStringManager::~CPDStringManager()
106 //void CPDStringManager::init(CPDSLib* lib)
112 // CUnifiedNetwork::getInstance()->addCallbackArray(PDStringManagerCbArray, sizeof(PDStringManagerCbArray)/sizeof(PDStringManagerCbArray[0]));
121 // * Get string entry (allocate a new entry if not yet in container)
123 //CPDStringManager::TEntryId CPDStringManager::getEntryIdNonConst(const ucstring& str)
125 // THash hash = getHash(str);
126 // TEntryId entryId = InvalidEntryId;
128 // if (_HashTable.size() > hash)
129 // entryId = _HashTable[hash];
131 // while (entryId != InvalidEntryId)
133 // const CStringEntry& entry = _StringEntries[entryId];
135 // if (entry.String == str)
137 // // DONE BY NICO : this forces the lib to update the string id value of the entry. Thus, EGS callbacks are called.
138 // // The real problem is that entries are never removed from _StringEntries. So when we add a string that should have been previously removed, setStringId is never called... )
139 // setStringId(str, entry.StringId);
143 // entryId = entry.NextInHash;
146 // // allocate new entry
147 // entryId = _StringEntries.size();
148 // _StringEntries.resize(entryId+1);
150 // // check hash table size
151 // if (_HashTable.size() <= hash)
152 // _HashTable.resize(PD_STRING_HASHTABLE_SIZE, InvalidEntryId);
155 // CStringEntry& entry = _StringEntries[entryId];
157 // entry.String = str;
158 // entry.Hash = hash;
159 // entry.NextInHash = _HashTable[hash];
161 // // link entry in hash table
162 // _HashTable[hash] = entryId;
164 // if (_PDSLib != NULL)
166 // storeStringInIOS(str);
174 // * Compares 2 ucchar strings
176 //bool CPDStringManager::compare(const ucchar* a, const ucchar* b)
178 // while (*a == *b && *a != 0)
190 // * Explicitly add string to manager
191 // * \param eid is the associated entity id
192 // * \param string is the string to add
193 // * \return the persistant string id
195 //void CPDStringManager::addString(NLMISC::CEntityId eid, const ucstring& str, bool addToLog)
197 // TEntryId entry = getEntryIdNonConst(str);
199 // if (_PDSLib != NULL)
201 // // client mode, send mapping to PDS
202 // _PDSLib->addString(eid, str);
205 // if ((_PDSLib == NULL && addToLog) || (_PDSLib != NULL && !_PDSLib->PDSUsed() && PDEnableStringLog))
207 // // PDS mode, log mapping
208 // _Log.Actions.push_back(CLogAction());
209 // _Log.Actions.back().MapId = true;
210 // _Log.Actions.back().EntityId = eid;
211 // _Log.Actions.back().String = str;
214 // mapEid(eid, entry);
220 //void CPDStringManager::unmap(NLMISC::CEntityId eid, bool addToLog)
222 // TEIdMap::iterator it = _EIdMap.find(eid);
223 // if (it == _EIdMap.end())
226 // if (_PDSLib != NULL)
228 // // client mode, send unmapping to PDS
229 // _PDSLib->unmapString(eid);
232 // if ((_PDSLib == NULL && addToLog) || (_PDSLib != NULL && !_PDSLib->PDSUsed() && PDEnableStringLog))
234 // // PDS mode, log unmapping
235 // _Log.Actions.push_back(CLogAction());
236 // _Log.Actions.back().MapId = false;
237 // _Log.Actions.back().EntityId = eid;
240 // CStringEntry& entry = _StringEntries[(*it).second];
242 // _EIdMap.erase(it);
244 // // remove from mapped eids
245 // std::vector<NLMISC::CEntityId>::iterator ite;
246 // for (ite=entry.MappedIds.begin(); ite!=entry.MappedIds.end(); )
249 // ite = entry.MappedIds.erase(ite);
257 // * Set string callback
258 // * This callback is called when the string id is received from the IOS.
259 // * That is when string id is ready to be used
261 //void CPDStringManager::setCallback(TStringCallback callback)
263 // _Callback = callback;
270 // * Display Manager content
272 //void CPDStringManager::display(NLMISC::CLog* log) const
279 // * Serial String Manager
281 //void CPDStringManager::serial(NLMISC::IStream& f)
283 // H_AUTO( PDSSM_SERIAL );
284 // f.serialCheck((uint32)'PDSM');
285 // uint version = f.serialVersion(0);
288 // H_AUTO( PDSSM_SERIAL_ENTRIES );
289 // f.serialCont(_StringEntries);
292 // H_AUTO( PDSSM_SERIAL_EIDMAP );
293 // f.serialCont(_EIdMap);
296 // if (f.isReading())
298 // H_AUTO( PDSSM_SERIAL_BUILDVOLATILEDATA );
299 // buildVolatileData();
305 // * Set String (PDS side)
308 //bool CPDStringManager::setString(const NLMISC::CEntityId& eid, TEntryId id, const ucstring& str)
310 // bool success = true;
312 // if (id >= _StringEntries.size())
314 // // alloc string entry
315 // _StringEntries.resize(id+1);
318 // CStringEntry& entry = _StringEntries[id];
320 // entry.Hash = getHash(str);
321 // entry.String = str;
323 // // link in hash table
324 // if (_HashTable.size() <= entry.Hash)
325 // _HashTable.resize(PD_STRING_HASHTABLE_SIZE, InvalidEntryId);
327 // entry.NextInHash = _HashTable[entry.Hash];
329 // else if (_StringEntries[id].String != str)
331 // // entry was alread filled !
332 // nlwarning("CPDStringManager::setString(): entry '%d' already set, entry is kept unchanged", id);
336 // _EIdMap[eid] = id;
347 //void CPDStringManager::setStringId(const ucstring& str, TStringId id)
349 // THash hash = getHash(str);
350 // TEntryId entryId = InvalidEntryId;
352 // if (_HashTable.size() >= hash)
354 // entryId = _HashTable[hash];
356 // while (entryId != InvalidEntryId)
358 // CStringEntry& entry = _StringEntries[entryId];
360 // if (entry.String == str)
362 // entry.StringId = id;
363 // _StringIdMap[id] = entryId;
366 // entryId = entry.NextInHash;
371 // if (_Callback != NULL)
372 // _Callback(str, id);
378 // * Build All String Associations
380 //void CPDStringManager::buildStringAssociation()
383 // for (i=0; i<CPDSLib::_Libs.size(); ++i)
385 // CPDSLib* lib = CPDSLib::_Libs[i];
387 // lib->getStringManager().askAssociations();
393 // * Ask Associations
395 //void CPDStringManager::askAssociations()
398 // for (i=0; i<_StringEntries.size(); ++i)
400 // storeStringInIOS(_StringEntries[i].String);
408 // * Rebuild volatile data
410 //void CPDStringManager::buildVolatileData()
412 // static bool alreadyBuilt = false;
415 //// if(alreadyBuilt)
416 //// nlstopex(("buildVolatileData() called 2 times, BEN, please fix me!!!"));
419 // nlwarning("buildVolatileData() called 2 times, BEN, please fix me!!!");
422 // _HashTable.clear();
425 // for (i=0; i<_StringEntries.size(); ++i)
427 // CStringEntry& entry = _StringEntries[i];
429 // entry.Hash = getHash(entry.String);
431 // if (_HashTable.size() <= entry.Hash)
432 // _HashTable.resize(PD_STRING_HASHTABLE_SIZE, InvalidEntryId);
434 // entry.NextInHash = _HashTable[entry.Hash];
435 // _HashTable[entry.Hash] = i;
437 // entry.MappedIds.clear();
440 // TEIdMap::const_iterator it;
441 // for (it=_EIdMap.begin(); it!=_EIdMap.end(); ++it)
443 // CStringEntry& entry = _StringEntries[(*it).second];
444 // entry.MappedIds.push_back((*it).first);
447 // alreadyBuilt = true;
452 // * Load String manager default file (to be used by client when PDS is not connected)
454 //bool CPDStringManager::load()
456 // if (_PDSLib == NULL)
459 // std::string logDir = _PDSLib->getLogDirectory();
461 // if (!CFile::isDirectory(logDir))
463 // if (!CFile::createDirectoryTree(logDir))
465 // nlwarning("Failed to create log root directory '%s'", logDir.c_str());
468 // if (!CFile::setRWAccess(logDir))
470 // nlwarning("Failed, can't set RW access to directory '%s'", logDir.c_str());
474 // return load(logDir);
478 // * Save String manager default file (to be used by client when PDS is not connected)
480 //bool CPDStringManager::save()
482 // if (_PDSLib == NULL)
485 // std::string logDir = _PDSLib->getLogDirectory();
487 // if (!CFile::isDirectory(logDir))
489 // if (!CFile::createDirectoryTree(logDir))
491 // nlwarning("Failed to create log root directory '%s'", logDir.c_str());
494 // if (!CFile::setRWAccess(logDir))
496 // nlwarning("Failed, can't set RW access to directory '%s'", logDir.c_str());
500 // return save(logDir);
504 // * Load String manager file
506 //bool CPDStringManager::load(const std::string& path)
508 // std::string filename = getFile(path);
510 // if (!CFile::fileExists(filename))
512 // nlinfo("CPDStringManager::load(): file '%s' doesn't exist, assumes string manager empty", filename.c_str());
517 // if (!file.open(filename))
519 // nlwarning("CPDStringManager::load(): failed to load file '%s', string manager left as is", filename.c_str());
527 // catch (Exception& e)
529 // nlwarning("CPDStringManager::load(): failed to load file '%s', exception in serial '%s'", filename.c_str(), e.what());
537 // * Save String manager file
539 //bool CPDStringManager::save(const std::string& path)
541 // std::string filename = getFile(path);
544 // if (!file.open(filename))
546 // nlwarning("CPDStringManager::save(): failed to save file '%s', string manager left as is", filename.c_str());
554 // catch (Exception& e)
556 // nlwarning("CPDStringManager::save(): failed to save file '%s', exception in serial '%s'", filename.c_str(), e.what());
564 // * Get String manager filename
566 //std::string CPDStringManager::getFile(const std::string& path)
568 // return CPath::standardizePath(path) + "string_manager.bin";
575 //bool CPDStringManager::applyLog(NLMISC::IStream& s)
581 // catch (Exception &e)
583 // nlwarning("CPDStringManager::applyLog(): failed to apply log from stream, exception in serial '%s'", e.what());
588 // for (i=0; i<_Log.Actions.size(); ++i)
590 // CLogAction& action = _Log.Actions[i];
594 // addString(action.EntityId, action.String, false);
598 // unmap(action.EntityId, false);
602 // _Log.Actions.clear();
610 //bool CPDStringManager::storeLog(NLMISC::IStream& s)
616 // catch (Exception &e)
618 // nlwarning("CPDStringManager::storeLog(): failed to store log to stream, exception in serial '%s'", e.what());
622 // _Log.Actions.clear();
630 //bool CPDStringManager::isLogFileName(const std::string& filename, CTimestamp& timestamp)
633 // if (NLMISC::CFile::getExtension(filename) != "xml" ||
634 // sscanf(NLMISC::CFile::getFilenameWithoutExtension(filename).c_str(), "string_%s", &buffer) != 1)
636 // timestamp.fromString(buffer);
641 // * Store string in IOS
643 //void CPDStringManager::storeStringInIOS(const ucstring& str)
645 // CMessage msgios("STORE_STRING");
646 // msgios.serial( const_cast<ucstring&>(str) );
647 // CUnifiedNetwork::getInstance()->send("IOS", msgios);
649 // _NbProcessingStoreStringRequests++;
653 // * Returns true if IOS has not processed all store string requests
655 //bool CPDStringManager::isWaitingIOSStoreStringResult()
657 // return (_NbProcessingStoreStringRequests != 0);