DataCache.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "DataCache.h"
  9. #include <AzCore/Casting/numeric_cast.h>
  10. #include <AzCore/JSON/stringbuffer.h>
  11. #include <AzCore/JSON/writer.h>
  12. #include <AzCore/std/smart_ptr/make_shared.h>
  13. namespace Metastream
  14. {
  15. void DataCache::AddToCache(const std::string& tableName, const std::string& key, const char* value)
  16. {
  17. DocumentPtr doc(FindDoc(tableName));
  18. auto jsonValue = doc->ToJson(value);
  19. doc->Add(key, jsonValue);
  20. }
  21. void DataCache::AddToCache(const std::string& tableName, const std::string& key, bool value)
  22. {
  23. DocumentPtr doc(FindDoc(tableName));
  24. auto jsonValue = doc->ToJson(value);
  25. doc->Add(key, jsonValue);
  26. }
  27. void DataCache::AddToCache(const std::string& tableName, const std::string& key, const AZ::Vector3& value)
  28. {
  29. DocumentPtr doc(FindDoc(tableName));
  30. auto jsonValue = doc->ToJson(value);
  31. doc->Add(key, jsonValue);
  32. }
  33. void DataCache::AddToCache(const std::string& tableName, const std::string& key, double value)
  34. {
  35. DocumentPtr doc(FindDoc(tableName));
  36. auto jsonValue = doc->ToJson(value);
  37. doc->Add(key, jsonValue);
  38. }
  39. void DataCache::AddToCache(const std::string& tableName, const std::string& key, AZ::u64 value)
  40. {
  41. DocumentPtr doc(FindDoc(tableName));
  42. auto jsonValue = doc->ToJson(value);
  43. doc->Add(key, jsonValue);
  44. }
  45. void DataCache::AddToCache(const std::string& tableName, const std::string& key, AZ::s64 value)
  46. {
  47. DocumentPtr doc(FindDoc(tableName));
  48. auto jsonValue = doc->ToJson(value);
  49. doc->Add(key, jsonValue);
  50. }
  51. void DataCache::AddToArray(const std::string& tableName, const std::string& arrayName, const char* value)
  52. {
  53. DocumentPtr doc(FindDoc(tableName));
  54. auto jsonValue = doc->ToJson(value);
  55. doc->AddToArray(arrayName, jsonValue);
  56. }
  57. void DataCache::AddToArray(const std::string& tableName, const std::string& arrayName, bool value)
  58. {
  59. DocumentPtr doc(FindDoc(tableName));
  60. auto jsonValue = doc->ToJson(value);
  61. doc->AddToArray(arrayName, jsonValue);
  62. }
  63. void DataCache::AddToArray(const std::string& tableName, const std::string& arrayName, const AZ::Vector3& value)
  64. {
  65. DocumentPtr doc(FindDoc(tableName));
  66. auto jsonValue = doc->ToJson(value);
  67. doc->AddToArray(arrayName, jsonValue);
  68. }
  69. void DataCache::AddToArray(const std::string& tableName, const std::string& arrayName, double value)
  70. {
  71. DocumentPtr doc(FindDoc(tableName));
  72. auto jsonValue = doc->ToJson(value);
  73. doc->AddToArray(arrayName, jsonValue);
  74. }
  75. void DataCache::AddToArray(const std::string& tableName, const std::string& arrayName, AZ::u64 value)
  76. {
  77. DocumentPtr doc(FindDoc(tableName));
  78. auto jsonValue = doc->ToJson(value);
  79. doc->AddToArray(arrayName, jsonValue);
  80. }
  81. void DataCache::AddToArray(const std::string& tableName, const std::string& arrayName, AZ::s64 value)
  82. {
  83. DocumentPtr doc(FindDoc(tableName));
  84. auto jsonValue = doc->ToJson(value);
  85. doc->AddToArray(arrayName, jsonValue);
  86. }
  87. void DataCache::AddToObject(const std::string& tableName, const std::string& objName, const std::string& key, const char* value)
  88. {
  89. DocumentPtr doc(FindDoc(tableName));
  90. auto jsonValue = doc->ToJson(value);
  91. doc->AddToObject(objName, key, jsonValue);
  92. }
  93. void DataCache::AddToObject(const std::string& tableName, const std::string& objName, const std::string& key, bool value)
  94. {
  95. DocumentPtr doc(FindDoc(tableName));
  96. auto jsonValue = doc->ToJson(value);
  97. doc->AddToObject(objName, key, jsonValue);
  98. }
  99. void DataCache::AddToObject(const std::string& tableName, const std::string& objName, const std::string& key, const AZ::Vector3& value)
  100. {
  101. DocumentPtr doc(FindDoc(tableName));
  102. auto jsonValue = doc->ToJson(value);
  103. doc->AddToObject(objName, key, jsonValue);
  104. }
  105. void DataCache::AddToObject(const std::string& tableName, const std::string& objName, const std::string& key, double value)
  106. {
  107. DocumentPtr doc(FindDoc(tableName));
  108. auto jsonValue = doc->ToJson(value);
  109. doc->AddToObject(objName, key, jsonValue);
  110. }
  111. void DataCache::AddToObject(const std::string& tableName, const std::string& objName, const std::string& key, AZ::u64 value)
  112. {
  113. DocumentPtr doc(FindDoc(tableName));
  114. auto jsonValue = doc->ToJson(value);
  115. doc->AddToObject(objName, key, jsonValue);
  116. }
  117. void DataCache::AddToObject(const std::string& tableName, const std::string& objName, const std::string& key, AZ::s64 value)
  118. {
  119. DocumentPtr doc(FindDoc(tableName));
  120. auto jsonValue = doc->ToJson(value);
  121. doc->AddToObject(objName, key, jsonValue);
  122. }
  123. void DataCache::AddArrayToCache(const std::string& tableName, const std::string& key, const std::string& arrayName)
  124. {
  125. DocumentPtr doc(FindDoc(tableName));
  126. doc->AddArray(key, arrayName);
  127. }
  128. void DataCache::AddObjectToCache(const std::string& tableName, const std::string& key, const std::string& objectName)
  129. {
  130. DocumentPtr doc(FindDoc(tableName));
  131. doc->AddObject(key, objectName);
  132. }
  133. void DataCache::AddArrayToObject(const std::string& tableName, const std::string& destObjName, const std::string& key, const std::string& srcArrayName)
  134. {
  135. DocumentPtr doc(FindDoc(tableName));
  136. doc->AddArrayToObject(destObjName, key, srcArrayName);
  137. }
  138. void DataCache::AddObjectToObject(const std::string& tableName, const std::string& destObjName, const std::string& key, const std::string& srcObjName)
  139. {
  140. DocumentPtr doc(FindDoc(tableName));
  141. doc->AddObjectToObject(destObjName, key, srcObjName);
  142. }
  143. void DataCache::AddObjectToArray(const std::string& tableName, const std::string& destArrayName, const std::string& srcObjectName)
  144. {
  145. DocumentPtr doc(FindDoc(tableName));
  146. doc->AddObjectToArray(destArrayName, srcObjectName);
  147. }
  148. std::string DataCache::GetDatabasesJSON() const
  149. {
  150. AZStd::lock_guard<AZStd::mutex> lock(m_mutexDatabase);
  151. rapidjson::Document jsonDoc;
  152. jsonDoc.SetObject();
  153. rapidjson::Value dbNames(rapidjson::kArrayType);
  154. for (const auto& i : m_database)
  155. {
  156. rapidjson::Value name;
  157. name.SetString(i.first.c_str(), jsonDoc.GetAllocator());
  158. dbNames.PushBack(name, jsonDoc.GetAllocator());
  159. }
  160. jsonDoc.AddMember("tables", dbNames, jsonDoc.GetAllocator());
  161. rapidjson::StringBuffer buffer;
  162. buffer.Clear();
  163. rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  164. jsonDoc.Accept(writer);
  165. return std::string(buffer.GetString());
  166. }
  167. std::string DataCache::GetTableKeysJSON(const std::string& tableName) const
  168. {
  169. AZStd::lock_guard<AZStd::mutex> lock(m_mutexDatabase);
  170. std::string json;
  171. auto it = m_database.find(tableName);
  172. if (it != m_database.end())
  173. {
  174. json = it->second->GetKeysJSON();
  175. }
  176. return json;
  177. }
  178. std::string DataCache::GetTableKeyValuesJSON(const std::string& tableName, const std::vector<std::string>& keyList) const
  179. {
  180. AZStd::lock_guard<AZStd::mutex> lock(m_mutexDatabase);
  181. std::string json;
  182. auto it = m_database.find(tableName);
  183. if (it != m_database.end())
  184. {
  185. json = it->second->GetKeyValuesJSON(keyList);
  186. }
  187. return json;
  188. }
  189. void DataCache::ClearCache()
  190. {
  191. AZStd::lock_guard<AZStd::mutex> lock(m_mutexDatabase);
  192. m_database.clear();
  193. }
  194. DataCache::DocumentPtr DataCache::FindDoc(const std::string& tableName)
  195. {
  196. AZStd::lock_guard<AZStd::mutex> lock(m_mutexDatabase);
  197. DocumentPtr doc;
  198. auto docItr = m_database.find(tableName);
  199. if (docItr == m_database.end())
  200. {
  201. doc = AZStd::make_shared<Document>();
  202. m_database[tableName] = doc;
  203. }
  204. else
  205. {
  206. doc = docItr->second;
  207. }
  208. return doc;
  209. }
  210. DataCache::Document::Document()
  211. : m_jsonDoc()
  212. , m_allocator(m_jsonDoc.GetAllocator())
  213. {
  214. m_jsonDoc.SetObject();
  215. }
  216. DataCache::Document::~Document()
  217. {
  218. m_jsonValues.clear();
  219. }
  220. std::string DataCache::Document::GetKeysJSON() const
  221. {
  222. AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
  223. rapidjson::Document jsonDoc;
  224. jsonDoc.SetObject();
  225. rapidjson::Value keyNames(rapidjson::kArrayType);
  226. for (rapidjson::Value::ConstMemberIterator itr = m_jsonDoc.MemberBegin(); itr != m_jsonDoc.MemberEnd(); ++itr)
  227. {
  228. rapidjson::Value name;
  229. name.SetString(itr->name.GetString(), jsonDoc.GetAllocator());
  230. keyNames.PushBack(name, jsonDoc.GetAllocator());
  231. }
  232. jsonDoc.AddMember("keys", keyNames, jsonDoc.GetAllocator());
  233. rapidjson::StringBuffer buffer;
  234. buffer.Clear();
  235. rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  236. jsonDoc.Accept(writer);
  237. return std::string(buffer.GetString());
  238. }
  239. std::string DataCache::Document::GetKeyValuesJSON(const std::vector<std::string>& keyList) const
  240. {
  241. AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
  242. rapidjson::StringBuffer buffer;
  243. buffer.Clear();
  244. rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  245. if ((keyList.size() == 1) && (keyList[0] == "*"))
  246. {
  247. m_jsonDoc.Accept(writer);
  248. }
  249. else
  250. {
  251. rapidjson::Document jsonDoc;
  252. jsonDoc.SetObject();
  253. for (rapidjson::Value::ConstMemberIterator itr = m_jsonDoc.MemberBegin(); itr != m_jsonDoc.MemberEnd(); ++itr)
  254. {
  255. std::string keyName(itr->name.GetString());
  256. if (std::find(keyList.cbegin(), keyList.cend(), keyName) != keyList.cend())
  257. {
  258. // do a deep copy for this key...
  259. rapidjson::Value v;
  260. v.CopyFrom(itr->value, jsonDoc.GetAllocator());
  261. jsonDoc.AddMember(rapidjson::Value().SetString(itr->name.GetString(), jsonDoc.GetAllocator()), v, jsonDoc.GetAllocator());
  262. }
  263. }
  264. jsonDoc.Accept(writer);
  265. }
  266. return std::string(buffer.GetString());
  267. }
  268. std::string DataCache::Document::GetJSON() const
  269. {
  270. AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
  271. rapidjson::StringBuffer buffer;
  272. buffer.Clear();
  273. rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  274. m_jsonDoc.Accept(writer);
  275. return std::string(buffer.GetString());
  276. }
  277. void DataCache::Document::Add(const std::string& key, rapidjson::Value& value)
  278. {
  279. AZStd::lock_guard<AZStd::mutex> lock(m_mutex);
  280. if (m_jsonDoc.HasMember(key.c_str()))
  281. m_jsonDoc.RemoveMember(ToJson(key));
  282. m_jsonDoc.AddMember(ToJson(key), value, m_allocator);
  283. }
  284. void DataCache::Document::AddToArray(const std::string& arrayName, rapidjson::Value& value)
  285. {
  286. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  287. rapidJsonValuePtr rapidValue(FindValue(arrayName, ValueType::Array));
  288. rapidValue->PushBack(value, m_allocator);
  289. }
  290. void DataCache::Document::AddToObject(const std::string& objectName, const std::string& key, rapidjson::Value& value)
  291. {
  292. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  293. rapidJsonValuePtr rapidValue(FindValue(objectName, ValueType::Object));
  294. if (rapidValue->HasMember(key.c_str()))
  295. rapidValue->RemoveMember(ToJson(key));
  296. rapidValue->AddMember(ToJson(key), value, m_allocator);
  297. }
  298. void DataCache::Document::AddArray(const std::string& key, const std::string& arrayName)
  299. {
  300. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  301. rapidJsonValuePtr rapidValue(FindValue(arrayName, ValueType::Array));
  302. Add(key, *rapidValue);
  303. RemoveValue(arrayName, ValueType::Array);
  304. }
  305. void DataCache::Document::AddObject(const std::string& key, const std::string& objectName)
  306. {
  307. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  308. rapidJsonValuePtr rapidValue(FindValue(objectName, ValueType::Object));
  309. Add(key, *rapidValue);
  310. RemoveValue(objectName, ValueType::Object);
  311. }
  312. void DataCache::Document::AddArrayToObject(const std::string& destObjName, const std::string& key, const std::string& srcArrayName)
  313. {
  314. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  315. rapidJsonValuePtr jsonDest(FindValue(destObjName, ValueType::Object));
  316. rapidJsonValuePtr jsonSrc(FindValue(srcArrayName, ValueType::Array));
  317. jsonDest->AddMember(ToJson(key), *jsonSrc, m_allocator);
  318. RemoveValue(srcArrayName, ValueType::Array);
  319. }
  320. void DataCache::Document::AddObjectToObject(const std::string& destObjName, const std::string& key, const std::string& srcObjName)
  321. {
  322. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  323. rapidJsonValuePtr jsonDest(FindValue(destObjName, ValueType::Object));
  324. rapidJsonValuePtr jsonSrc(FindValue(srcObjName, ValueType::Object));
  325. jsonDest->AddMember(ToJson(key), *jsonSrc, m_allocator);
  326. RemoveValue(srcObjName, ValueType::Object);
  327. }
  328. void DataCache::Document::AddObjectToArray(const std::string& destArrayName, const std::string& srcObjectName)
  329. {
  330. AZStd::lock_guard<AZStd::mutex> lock(m_mutexJsonArray);
  331. rapidJsonValuePtr jsonDest(FindValue(destArrayName, ValueType::Array));
  332. rapidJsonValuePtr jsonSrc(FindValue(srcObjectName, ValueType::Object));
  333. jsonDest->PushBack(*jsonSrc, m_allocator);
  334. RemoveValue(srcObjectName, ValueType::Object);
  335. }
  336. rapidjson::Value DataCache::Document::ToJson(const std::string& value)
  337. {
  338. rapidjson::Value v;
  339. v.SetString(value.c_str(), aznumeric_cast<rapidjson::SizeType>(value.size()), m_allocator);
  340. return v;
  341. }
  342. rapidjson::Value DataCache::Document::ToJson(const char* value)
  343. {
  344. rapidjson::Value v;
  345. v.SetString(value == nullptr ? "" : value, m_allocator);
  346. return v;
  347. }
  348. rapidjson::Value DataCache::Document::ToJson(bool value)
  349. {
  350. rapidjson::Value v;
  351. v.SetBool(value);
  352. return v;
  353. }
  354. rapidjson::Value DataCache::Document::ToJson(const AZ::Vector3& value)
  355. {
  356. rapidjson::Value v(rapidjson::kArrayType);
  357. v.PushBack(ToJson(value.GetX()), m_allocator);
  358. v.PushBack(ToJson(value.GetY()), m_allocator);
  359. v.PushBack(ToJson(value.GetZ()), m_allocator);
  360. return v;
  361. }
  362. rapidjson::Value DataCache::Document::ToJson(double value)
  363. {
  364. return rapidjson::Value(value);
  365. }
  366. rapidjson::Value DataCache::Document::ToJson(AZ::u64 value)
  367. {
  368. uint64_t uintValue = value;
  369. return rapidjson::Value(uintValue);
  370. }
  371. rapidjson::Value DataCache::Document::ToJson(AZ::s64 value)
  372. {
  373. int64_t intValue = value;
  374. return rapidjson::Value(intValue);
  375. }
  376. DataCache::Document::rapidJsonValuePtr DataCache::Document::FindValue(const std::string& name, ValueType type)
  377. {
  378. rapidJsonValuePtr valuePtr;
  379. std::string lookupName(name + std::string((type == ValueType::Array) ? "_Array" : "_Object"));
  380. auto itr = m_jsonValues.find(lookupName);
  381. if (itr == m_jsonValues.end())
  382. {
  383. valuePtr = AZStd::make_shared<rapidjson::Value>((type == ValueType::Array) ? rapidjson::kArrayType : rapidjson::kObjectType);
  384. m_jsonValues[lookupName] = valuePtr;
  385. }
  386. else
  387. {
  388. valuePtr = itr->second;
  389. }
  390. return valuePtr;
  391. }
  392. void DataCache::Document::RemoveValue(const std::string& name, ValueType type)
  393. {
  394. std::string lookupName(name + std::string((type == ValueType::Array) ? "_Array" : "_Object"));
  395. auto itr = m_jsonValues.find(lookupName);
  396. if (itr != m_jsonValues.end())
  397. {
  398. m_jsonValues.erase(itr);
  399. }
  400. }
  401. }