#ifndef __BlackList_C_ #define __BlackList_C_ #include "../misc_framework/DataNodes.h" /* This file is responsible for blocking certain stocks at run time. * * We always start by loading all symbols we find in data/Symbols.txt. * BlackList allows us to remove some of those stocks while we are running. * * To black-list a stock, add the stock symbol to data/black-list.txt. * * The idea is that you only add to this list over time. In general, * if you remove a symbol, that will not un-black-list the symbol. * However, if you add a symbol then quickly remove it, there is no * guarantee that we even saw the change. Just don't do that. * * The file should have one symbol per line. * The file can have Unix or DOS line endings. * The blank lines and blank spaces at the beginning or end of a line are * ignored. * * When we read the file we debounce any changes. In case we are reading * while someone is writing. So any time we see a change we wait 5 seconds * and take another look. The file must stay the same for 5 seconds before * we actually use it. Ideally you should always use mv to change a file * atomically. However, I suspect this is being copied over using scp. * I would hate to black-list "A" and later realize I was supposed to * black-list "APPL"! * * This code rereads the file once per minute. * * This code sends a lot of details to the log file. I'd hate to accidentally * turn off the wrong symbol, or ignore a valid request. But if I do, I want * to know it! */ class BlackList : public DataNode { private: class FileWatcher : public DataNode { private: TimerThread::Helper _periodicTimer; TimerThread::Helper _singleTimer; std::string _body; std::set< std::string > _blackListed; bool _waitingForConfirmation; static std::string getFileContents(); void addStrings(); // From BroadcastMessageListener via DataNode virtual void onBroadcast(BroadcastMessage &message, int msgId); FileWatcher(DataNodeArgument const &args); friend class DataNode; public: bool isBlackListed(std::string const &symbol) const { return _blackListed.count(symbol); } static DataNodeLink *find(DataNodeListener *listener, int msgId, FileWatcher *&node); }; const std::string _symbol; FileWatcher *_fileWatcher; bool _blackListed; // From DataNodeListener via DataNode virtual void onWakeup(int msgId); BlackList(DataNodeArgument const &args); friend class DataNode; public: bool isBlackListed() const { return _blackListed; } static DataNodeLink *find(DataNodeListener *listener, int msgId, BlackList *&node, std::string const &symbol); static DataNodeLink *find(BlackList *&node, std::string const &symbol); }; #endif