FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize, const bool deleteOld, const int age, const FileLogAgeType ageType) : m_backup(backup) , m_maxSize(maxSize) , m_logFile(nullptr) { m_flusher.setInterval(0); m_flusher.setSingleShot(true); connect(&m_flusher, &QTimer::timeout, this, &FileLogger::flushLog); changePath(path); if (deleteOld) this->deleteOld(age, ageType); const Logger *const logger = Logger::instance(); foreach (const Log::Msg &msg, logger->getMessages()) addLogMessage(msg); connect(logger, &Logger::newLogMessage, this, &FileLogger::addLogMessage); }
ExecutionLog::ExecutionLog(QWidget *parent) : QWidget(parent) , ui(new Ui::ExecutionLog) , m_msgList(new LogListWidget(MAX_LOG_MESSAGES)) , m_peerList(new LogListWidget(MAX_LOG_MESSAGES)) { ui->setupUi(this); ui->tabConsole->setTabIcon(0, GuiIconProvider::instance()->getIcon("view-calendar-journal")); ui->tabConsole->setTabIcon(1, GuiIconProvider::instance()->getIcon("view-filter")); ui->tabGeneral->layout()->addWidget(m_msgList); ui->tabBan->layout()->addWidget(m_peerList); const Logger* const logger = Logger::instance(); foreach (const Log::Msg& msg, logger->getMessages()) addLogMessage(msg); foreach (const Log::Peer& peer, logger->getPeers()) addPeerMessage(peer); connect(logger, SIGNAL(newLogMessage(const Log::Msg &)), SLOT(addLogMessage(const Log::Msg &))); connect(logger, SIGNAL(newLogPeer(const Log::Peer &)), SLOT(addPeerMessage(const Log::Peer &))); }
ExecutionLogWidget::ExecutionLogWidget(QWidget *parent, const Log::MsgTypes &types) : QWidget(parent) , m_ui(new Ui::ExecutionLogWidget) , m_peerList(new LogListWidget(MAX_LOG_MESSAGES)) { m_ui->setupUi(this); m_msgList = new LogListWidget(MAX_LOG_MESSAGES, Log::MsgTypes(types)); #ifndef Q_OS_MAC m_ui->tabConsole->setTabIcon(0, GuiIconProvider::instance()->getIcon("view-calendar-journal")); m_ui->tabConsole->setTabIcon(1, GuiIconProvider::instance()->getIcon("view-filter")); #endif m_ui->tabGeneral->layout()->addWidget(m_msgList); m_ui->tabBan->layout()->addWidget(m_peerList); const Logger *const logger = Logger::instance(); foreach (const Log::Msg &msg, logger->getMessages()) addLogMessage(msg); foreach (const Log::Peer &peer, logger->getPeers()) addPeerMessage(peer); connect(logger, &Logger::newLogMessage, this, &ExecutionLogWidget::addLogMessage); connect(logger, &Logger::newLogPeer, this, &ExecutionLogWidget::addPeerMessage); }
void_t Main::controlUserBroker(uint32_t requestId, uint64_t entityId, uint32_t controlCode, const byte_t* data, size_t size) { switch(controlCode) { case meguco_user_broker_control_refresh_orders: { List<meguco_user_broker_order_entity> newOrders; if(!broker->loadOrders(newOrders)) { addLogMessage(meguco_log_error, broker->getLastError()); return (void_t)connection.sendControlResponse(requestId, 0); } Map<int64_t, meguco_user_broker_order_entity*> sortedNewOrders; for(List<meguco_user_broker_order_entity>::Iterator i = newOrders.begin(), end = newOrders.end(); i != end; ++i) sortedNewOrders.insert((*i).entity.time, &*i); HashMap<uint64_t, meguco_user_broker_order_entity> ordersMapByRaw; for(HashMap<uint64_t, meguco_user_broker_order_entity>::Iterator i = orders2.begin(), end = orders2.end(); i != end; ++i) { meguco_user_broker_order_entity& order = *i; ordersMapByRaw.append(order.raw_id, order); } orders2.clear(); for(Map<int64_t, meguco_user_broker_order_entity*>::Iterator i = sortedNewOrders.begin(), end = sortedNewOrders.end(); i != end; ++i) { meguco_user_broker_order_entity& order = **i; HashMap<uint64_t, meguco_user_broker_order_entity>::Iterator it = ordersMapByRaw.find(order.raw_id); if(it == ordersMapByRaw.end() || it->entity.id == 0) { // add uint64_t id; if(connection.add(userBrokerOrdersTableId, order.entity, id)) { order.entity.id = id; orders2.append(order.entity.id, order); } } else { // update order.entity.id = it->entity.id; if(Memory::compare(&*it, &order, sizeof(order)) != 0 && connection.update(userBrokerOrdersTableId, order.entity)) orders2.append(order.entity.id, order); else orders2.append(order.entity.id, *it); ordersMapByRaw.remove(it); } } for(HashMap<uint64_t, meguco_user_broker_order_entity>::Iterator i = ordersMapByRaw.begin(), end = ordersMapByRaw.end(); i != end; ++i) { // remove meguco_user_broker_order_entity& order = *i; if(!connection.remove(userBrokerOrdersTableId, order.entity.id)) orders2.append(order.entity.id, order); } } return (void_t)connection.sendControlResponse(requestId, 0, 0); case meguco_user_broker_control_refresh_transactions: { List<meguco_user_broker_transaction_entity> newTransactions; if(!broker->loadTransactions(newTransactions)) { addLogMessage(meguco_log_error, broker->getLastError()); return (void_t)connection.sendControlResponse(requestId, 0); } Map<int64_t, meguco_user_broker_transaction_entity*> sortedNewTransactions; for(List<meguco_user_broker_transaction_entity>::Iterator i = newTransactions.begin(), end = newTransactions.end(); i != end; ++i) sortedNewTransactions.insert((*i).entity.time, &*i); HashMap<uint64_t, meguco_user_broker_transaction_entity> transactionsapByRaw; for(HashMap<uint64_t, meguco_user_broker_transaction_entity>::Iterator i = transactions2.begin(), end = transactions2.end(); i != end; ++i) { meguco_user_broker_transaction_entity& transaction = *i; transactionsapByRaw.append(transaction.raw_id, transaction); } transactions2.clear(); for(Map<int64_t, meguco_user_broker_transaction_entity*>::Iterator i = sortedNewTransactions.begin(), end = sortedNewTransactions.end(); i != end; ++i) { meguco_user_broker_transaction_entity& transaction = **i; HashMap<uint64_t, meguco_user_broker_transaction_entity>::Iterator it = transactionsapByRaw.find(transaction.raw_id); if(it == transactionsapByRaw.end() || it->entity.id == 0) { // add uint64_t id; if(connection.add(userBrokerTransactionsTableId, transaction.entity, id)) { transaction.entity.id = id; transactions2.append(transaction.entity.id, transaction); } } else { // update transaction.entity.id = it->entity.id; if(Memory::compare(&*it, &transaction, sizeof(transaction)) != 0 && connection.update(userBrokerTransactionsTableId, transaction.entity)) transactions2.append(transaction.entity.id, transaction); else transactions2.append(transaction.entity.id, *it); transactionsapByRaw.remove(it); } } for(HashMap<uint64_t, meguco_user_broker_transaction_entity>::Iterator i = transactionsapByRaw.begin(), end = transactionsapByRaw.end(); i != end; ++i) { // remove meguco_user_broker_transaction_entity& transaction = *i; if(!connection.remove(userBrokerTransactionsTableId, transaction.entity.id)) transactions2.append(transaction.entity.id, transaction); } } return (void_t)connection.sendControlResponse(requestId, 0, 0); case meguco_user_broker_control_refresh_balance: { meguco_user_broker_balance_entity newBalance; if(!broker->loadBalance(newBalance)) { addLogMessage(meguco_log_error, broker->getLastError()); return (void_t)connection.sendControlResponse(requestId, 0); } if(this->balance.entity.id == 0) { uint64_t id; if(connection.add(userBrokerBalanceTableId, newBalance.entity, id)) newBalance.entity.id = id; } else { newBalance.entity.id = this->balance.entity.id; connection.update(userBrokerBalanceTableId, newBalance.entity); } this->balance = newBalance; } return (void_t)connection.sendControlResponse(requestId, (const byte_t*)&balance, sizeof(meguco_user_broker_balance_entity)); case meguco_user_broker_control_create_order: if(size < sizeof(meguco_user_broker_order_entity)) return (void_t)connection.sendControlResponse(requestId, zlimdb_error_invalid_request); { const meguco_user_broker_order_entity& args = *(const meguco_user_broker_order_entity*)data; meguco_user_broker_order_entity newOrder; if(!broker->createOrder((meguco_user_broker_order_type)args.type, args.price, args.amount, args.total, newOrder)) { addLogMessage(meguco_log_error, broker->getLastError()); return (void_t)connection.sendControlResponse(requestId, 0); } newOrder.state = meguco_user_broker_order_open; newOrder.timeout = args.timeout; // add entity to user brokers table uint64_t id; if(!connection.add(userBrokerOrdersTableId, newOrder.entity, id)) return (void_t)connection.sendControlResponse(requestId, (uint16_t)connection.getErrno()); newOrder.entity.id = id; orders2.append(id, newOrder); // return entity id return (void_t)connection.sendControlResponse(requestId, (const byte_t*)&newOrder, sizeof(meguco_user_broker_order_entity)); } case meguco_user_broker_control_cancel_order: case meguco_user_broker_control_remove_order: { HashMap<uint64_t, meguco_user_broker_order_entity>::Iterator it = orders2.find(entityId); if(it == orders2.end()) return (void_t)connection.sendControlResponse(requestId, zlimdb_error_entity_not_found); meguco_user_broker_order_entity& order = *it; // cancel order if(order.state == meguco_user_broker_order_open) { if(!broker->cancelOrder(order.raw_id)) { addLogMessage(meguco_log_error, broker->getLastError()); return (void_t)connection.sendControlResponse(requestId, 0); } } // update order state if(controlCode == meguco_user_broker_control_cancel_order) { order.state = meguco_user_broker_order_canceled; if(!connection.update(userBrokerOrdersTableId, order.entity)) return (void_t)connection.sendControlResponse(requestId, (uint16_t)connection.getErrno()); } else { if(!connection.remove(userBrokerOrdersTableId, order.entity.id)) return (void_t)connection.sendControlResponse(requestId, (uint16_t)connection.getErrno()); orders2.remove(it); } // send answer return (void_t)connection.sendControlResponse(requestId, 0, 0); } case meguco_user_broker_control_update_order: if(size < sizeof(meguco_user_broker_control_update_order_params)) return (void_t)connection.sendControlResponse(requestId, zlimdb_error_invalid_request); { HashMap<uint64_t, meguco_user_broker_order_entity>::Iterator it = orders2.find(entityId); if(it == orders2.end()) return (void_t)connection.sendControlResponse(requestId, zlimdb_error_entity_not_found); meguco_user_broker_order_entity& order = *it; const meguco_user_broker_control_update_order_params& params = *(const meguco_user_broker_control_update_order_params*)data; // cancel order if(!broker->cancelOrder(order.raw_id)) { addLogMessage(meguco_log_error, broker->getLastError()); return (void_t)connection.sendControlResponse(requestId, 0); } // create new order with same id meguco_user_broker_order_entity newOrder; if(!broker->createOrder((meguco_user_broker_order_type)order.type, params.price, params.amount, params.total, newOrder)) { addLogMessage(meguco_log_error, broker->getLastError()); order.state = meguco_user_broker_order_error; } else { newOrder.entity.id = order.entity.id; newOrder.timeout = order.timeout; order = newOrder; order.state = meguco_user_broker_order_open; } // update order state in table if(!connection.update(userBrokerOrdersTableId, order.entity)) return (void_t)connection.sendControlResponse(requestId, (uint16_t)connection.getErrno()); // send answer if(order.state == meguco_user_broker_order_error) return (void_t)connection.sendControlResponse(requestId, 0); else return (void_t)connection.sendControlResponse(requestId, 0, 0); } default: return (void_t)connection.sendControlResponse(requestId, zlimdb_error_invalid_request); } }
bool_t Main::connect(const String& userName, uint64_t sessionId) { // close current connections delete broker; broker = 0; delete botSession; botSession = 0; // create session entity connection if(!connection.connect(*this)) return false; // subscribe to user session table String tablePrefix = String("users/") + userName + "/sessions/" + String::fromUInt64(sessionId); if(!connection.createTable(tablePrefix + "/session", sessionTableId)) return false; if(!connection.subscribe(sessionTableId, zlimdb_subscribe_flag_responder)) return false; simulation = true; uint32_t brokerId = 0; byte_t buffer[ZLIMDB_MAX_MESSAGE_SIZE]; while(connection.getResponse(buffer)) { for(const meguco_user_session_entity* userBrokerEntity = (const meguco_user_session_entity*)zlimdb_get_first_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_entity)); userBrokerEntity; userBrokerEntity = (const meguco_user_session_entity*)zlimdb_get_next_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_entity), &userBrokerEntity->entity)) { if(userBrokerEntity->entity.id != 1) continue; if(userBrokerEntity->mode == meguco_user_session_live) simulation = false; brokerId = userBrokerEntity->broker_id; } } if(connection.getErrno() != 0) return false; // get table ids (or create tables in case they do not exist) if(!connection.createTable(tablePrefix + "/transactions", transactionsTableId)) return false; if(!connection.createTable(tablePrefix + "/assets", assetsTableId)) return false; if(!connection.createTable(tablePrefix + "/orders", ordersTableId)) return false; if(!connection.createTable(tablePrefix + "/log", logTableId)) return false; if(!connection.createTable(tablePrefix + "/properties", propertiesTableId)) return false; if(!connection.createTable(tablePrefix + "/markers", markersTableId)) return false; // get broker String brokerTablePrefix = String("users/") + userName + "/brokers/" + String::fromUInt64(brokerId); if(!connection.findTable(brokerTablePrefix + "/broker", brokerTableId)) return false; if(!connection.queryEntity(brokerTableId, 1, *(zlimdb_entity*)buffer, sizeof(meguco_user_broker_entity), ZLIMDB_MAX_ENTITY_SIZE)) return false; const meguco_user_broker_entity* brokerEntity = (const meguco_user_broker_entity*)buffer; uint64_t brokerTypeId = brokerEntity->broker_type_id; // get broker type info uint32_t brokersTableId; if(!connection.findTable("brokers", brokersTableId)) return false; meguco_broker_type_entity* brokerType = (meguco_broker_type_entity*)buffer; if(!connection.queryEntity(brokersTableId, brokerTypeId, brokerType->entity, sizeof(meguco_broker_type_entity), sizeof(buffer))) return false; String marketName; if(!ZlimdbConnection::getString(brokerType->entity, sizeof(meguco_broker_type_entity), brokerType->name_size, marketName)) return false; size_t pos = 0; marketName.detach(); marketName.token('/', pos); String currencyComm = marketName.token('/', pos); String currencyBase = marketName.token('/', pos); // get broker orders table id if(!connection.findTable(brokerTablePrefix + "/orders", brokerOrdersTableId)) return false; // create local broker interface BotFactory botFactory; maxTradeAge = botFactory.getMaxTradeAge(); if(simulation) { // get broker balance meguco_user_broker_balance_entity balance; if(!getBrokerBalance(balance)) return false; broker = new SimBroker(*this, currencyBase, currencyComm, balance.fee, maxTradeAge); } else broker = new LiveBroker(*this, currencyBase, currencyComm); // get session orders if(!connection.query(ordersTableId)) return false; while(connection.getResponse(buffer)) { for(const meguco_user_broker_order_entity* order = (const meguco_user_broker_order_entity*)zlimdb_get_first_entity((const zlimdb_header*)buffer, sizeof(meguco_user_broker_order_entity)); order; order = (const meguco_user_broker_order_entity*)zlimdb_get_next_entity((const zlimdb_header*)buffer, sizeof(meguco_user_broker_order_entity), &order->entity)) broker->registerOrder(*order); } if(connection.getErrno() != 0) return false; // get session properties if(!connection.query(propertiesTableId)) return false; String name, value, unit; while(connection.getResponse(buffer)) { for(const meguco_user_session_property_entity* property = (const meguco_user_session_property_entity*)zlimdb_get_first_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_property_entity)); property; property = (const meguco_user_session_property_entity*)zlimdb_get_next_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_property_entity), &property->entity)) { size_t offset = sizeof(meguco_user_session_property_entity); if(!ZlimdbConnection::getString(property->entity, property->name_size, name, offset) || !ZlimdbConnection::getString(property->entity, property->value_size, value, offset) || !ZlimdbConnection::getString(property->entity, property->unit_size, unit, offset)) continue; broker->registerProperty(Bot::Property(*property, name, value, unit)); } } if(connection.getErrno() != 0) return false; // get live properties table if(simulation) { if(!connection.findTable(tablePrefix + "/properties.backup", livePropertiesTableId)) return false; if(!connection.query(livePropertiesTableId)) return false; while(connection.getResponse(buffer)) { String name, value, unit; for(const meguco_user_session_property_entity* property = (const meguco_user_session_property_entity*)zlimdb_get_first_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_property_entity)); property; property = (const meguco_user_session_property_entity*)zlimdb_get_next_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_property_entity), &property->entity)) { size_t offset = sizeof(meguco_user_session_property_entity); if(!ZlimdbConnection::getString(property->entity, property->name_size, name, offset)) continue; liveProperties.append(name); } } if(connection.getErrno() != 0) return false; } // get session assets if(!connection.query(assetsTableId)) return false; while(connection.getResponse(buffer)) { for(const meguco_user_session_asset_entity* asset = (const meguco_user_session_asset_entity*)zlimdb_get_first_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_asset_entity)); asset; asset = (const meguco_user_session_asset_entity*)zlimdb_get_next_entity((const zlimdb_header*)buffer, sizeof(meguco_user_session_asset_entity), &asset->entity)) broker->registerAsset(*asset); } if(connection.getErrno() != 0) return false; // instantiate bot implementation botSession = botFactory.createSession(*broker); // get trade history if(!connection.findTable(String("markets/") + marketName + "/trades", tradesTableId)) return false; int64_t serverTime, tableTime; if(!connection.sync(tradesTableId, serverTime, tableTime)) return false; if(!connection.subscribe(tradesTableId, zlimdb_query_type_since_time, tableTime - (simulation ? (7ULL * 24ULL * 60ULL * 60ULL * 1000ULL) : (maxTradeAge + 10 * 60 * 1000)), zlimdb_subscribe_flag_none)) return false; while(connection.getResponse(buffer)) { for(const meguco_trade_entity* trade = (const meguco_trade_entity*)zlimdb_get_first_entity((const zlimdb_header*)buffer, sizeof(meguco_trade_entity)); trade; trade = (const meguco_trade_entity*)zlimdb_get_next_entity((const zlimdb_header*)buffer, sizeof(meguco_trade_entity), &trade->entity)) broker->handleTrade(*botSession, *trade, true); } if(connection.getErrno() != 0) return false; if(simulation) addLogMessage(Time::time(), "synced"); return true; }