#ifndef __SimpleDatabaseFields_h_ #define __SimpleDatabaseFields_h_ #include #include "../shared/DatabaseWithRetry.h" #include "../shared/ThreadSafeWrapper.h" #include "DataFormat.h" /* This is data which is easy to access from the database and is often joined * with the alerts or top list tables. We read this data from the database * in an appropriate thread, and keep a cached copy available. This can be * updated in one thread while being used in other threads. */ // Similar to the way we handle std::map. Same interface, as much as possible, // so we can quickly switch between the two implementations. template< class KeyType, class ValueType > ValueType getProperty(std::unordered_map< KeyType, ValueType > const &properties, KeyType propertyName, ValueType defaultValue) { auto item = properties.find(propertyName); if (item == properties.end()) return defaultValue; else return item->second; } template< class KeyType , class ValueType > ValueType const * getProperty(std::unordered_map< KeyType, ValueType > const &properties, KeyType propertyName) { auto item = properties.find(propertyName); if (item == properties.end()) return NULL; else return &(item->second); } template< class KeyType , class ValueType > ValueType * getProperty(std::unordered_map< KeyType, ValueType > &properties, KeyType propertyName) { auto item = properties.find(propertyName); if (item == properties.end()) return NULL; else return &(item->second); } class CompanyNameInfo { public: std::unordered_map< std::string, std::string > values; ValueBox get(std::string symbol) const { if (std::string const *companyName = getProperty(values, symbol)) return *companyName; return ValueBox(); } ValueBox get(ValueBox const &symbol) const { bool valid; std::string value; symbol.getString(valid, value); if (valid) return get(value); else return ValueBox(); } }; class CompanyNameManager { private: CompanyNameManager(); static ThreadSafeWrapper< CompanyNameInfo > _current; static __thread ThreadSafeCache< CompanyNameInfo > *_cache; static ThreadSafeCache< CompanyNameInfo > &cache() { if (!_cache) _cache = new ThreadSafeCache< CompanyNameInfo >(_current); return *_cache; } static void set(CompanyNameInfo *newValue); public: static ValueBox get(ValueBox const &symbol) { return cache()->get(symbol); } static void load(DatabaseWithRetry &database); }; class NaicsInfo { public: struct Code { char code[6]; }; typedef std::unordered_map< std::string, Code > BySymbol; BySymbol _bySymbol; typedef std::map< std::string, std::string> ByCode; ByCode _byCode; ValueBox get(ValueBox const &symbol, int digits) const; void load(DatabaseWithRetry &database); }; class NaicsManager { private: NaicsManager(); static ThreadSafeWrapper< NaicsInfo > _current; static __thread ThreadSafeCache< NaicsInfo > *_cache; static ThreadSafeCache< NaicsInfo > &cache() { if (!_cache) _cache = new ThreadSafeCache< NaicsInfo >(_current); return *_cache; } public: static ValueBox get(ValueBox const &symbol, int digits) { return _current.get()->get(symbol, digits); }; static void load(DatabaseWithRetry &database); }; #endif