"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.8.166/src/server/core/ua_notification_item.cpp" (23 Feb 2021, 9882 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ua_notification_item.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** NetXMS - Network Management System
    3 ** Copyright (C) 2019-2020 Raden Solutions
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License as published by
    7 ** the Free Software Foundation; either version 2 of the License, or
    8 ** (at your option) any later version.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 ** GNU General Public License for more details.
   14 **
   15 ** You should have received a copy of the GNU General Public License
   16 ** along with this program; if not, write to the Free Software
   17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18 **
   19 ** File: ua_notification_item.cpp
   20 **
   21 **/
   22 
   23 #include "nxcore.h"
   24 
   25 Mutex g_userAgentNotificationListMutex;
   26 ObjectArray<UserAgentNotificationItem> g_userAgentNotificationList(0, 16, Ownership::True);
   27 
   28 /**
   29  * Init user agent messages
   30  */
   31 void InitUserAgentNotifications()
   32 {
   33    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
   34 
   35    DB_RESULT hResult = DBSelect(hdb, _T("SELECT id,message,objects,start_time,end_time,recall,on_startup,creation_time,created_by FROM user_agent_notifications"));
   36    if (hResult != nullptr)
   37    {
   38       int count = DBGetNumRows(hResult);
   39       for(int i = 0; i < count; i++)
   40       {
   41          g_userAgentNotificationList.add(new UserAgentNotificationItem(hResult, i));
   42       }
   43       DBFreeResult(hResult);
   44    }
   45    DBConnectionPoolReleaseConnection(hdb);
   46    DbgPrintf(2, _T("%d user agent messages loaded"), g_userAgentNotificationList.size());
   47 }
   48 
   49 /**
   50  * Delete expired user agent notifications
   51  */
   52 void DeleteExpiredUserAgentNotifications(DB_HANDLE hdb, UINT32 retentionTime)
   53 {
   54    g_userAgentNotificationListMutex.lock();
   55    time_t now = time(nullptr);
   56    Iterator<UserAgentNotificationItem> *it = g_userAgentNotificationList.iterator();
   57    while (it->hasNext())
   58    {
   59       UserAgentNotificationItem *uan = it->next();
   60       if((now - uan->getEndTime()) >= retentionTime && uan->hasNoRef())
   61       {
   62          it->remove();
   63          break;
   64       }
   65    }
   66    delete it;
   67    g_userAgentNotificationListMutex.unlock();
   68 
   69    TCHAR query[256];
   70    _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM user_agent_notifications WHERE end_time>=") INT64_FMT,
   71          static_cast<INT64>(now - retentionTime));
   72    DBQuery(hdb, query);
   73 
   74    _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("DELETE FROM user_agent_notifications WHERE creation_time>=") INT64_FMT _T(" AND end_time=0"),
   75          static_cast<INT64>(now - retentionTime));
   76    DBQuery(hdb, query);
   77 }
   78 
   79 void FillUserAgentNotificationsAll(NXCPMessage *msg, Node *node)
   80 {
   81    g_userAgentNotificationListMutex.lock();
   82    int base = VID_UA_NOTIFICATION_BASE;
   83    time_t now = time(nullptr);
   84    int count = 0;
   85    for (int i = 0; i < g_userAgentNotificationList.size(); i++)
   86    {
   87       UserAgentNotificationItem *uan = g_userAgentNotificationList.get(i);
   88       if ((uan->getEndTime() >= now) && !uan->isRecalled() && uan->isApplicable(node->getId()))
   89       {
   90          uan->fillMessage(base, msg, false);
   91          base += 10;
   92          count++;
   93       }
   94    }
   95    msg->setField(VID_UA_NOTIFICATION_COUNT, count);
   96    g_userAgentNotificationListMutex.unlock();
   97 }
   98 
   99 /**
  100  * Create new user agent notification
  101  */
  102 UserAgentNotificationItem *CreateNewUserAgentNotification(const TCHAR *message, const IntegerArray<uint32_t>& objects, time_t startTime, time_t endTime, bool onStartup, uint32_t userId)
  103 {
  104    g_userAgentNotificationListMutex.lock();
  105    UserAgentNotificationItem *uan = new UserAgentNotificationItem(message, objects, startTime, endTime, onStartup, userId);
  106    g_userAgentNotificationList.add(uan);
  107    uan->incRefCount();
  108    uan->incRefCount();
  109    g_userAgentNotificationListMutex.unlock();
  110 
  111    ThreadPoolExecute(g_clientThreadPool, uan, &UserAgentNotificationItem::processUpdate);
  112    NotifyClientSessions(NX_NOTIFY_USER_AGENT_MESSAGE_CHANGED, uan->getId());
  113    return uan;
  114 }
  115 
  116 /**
  117  * Create user agent message form database
  118  */
  119 UserAgentNotificationItem::UserAgentNotificationItem(DB_RESULT result, int row) : m_objects(64, 64)
  120 {
  121    m_id = DBGetFieldULong(result, row, 0);
  122    DBGetField(result, row, 1, m_message, MAX_USER_AGENT_MESSAGE_SIZE);
  123 
  124    TCHAR objectList[MAX_DB_STRING];
  125    DBGetField(result, row, 2, objectList, MAX_DB_STRING);
  126    int count;
  127    TCHAR **ids = SplitString(objectList, _T(','), &count);
  128    for(int i = 0; i < count; i++)
  129    {
  130       m_objects.add(_tcstoul(ids[i], nullptr, 10));
  131       MemFree(ids[i]);
  132    }
  133    MemFree(ids);
  134 
  135    m_startTime = DBGetFieldLong(result, row, 3);
  136    m_endTime = DBGetFieldLong(result, row, 4);
  137    m_recall = DBGetFieldLong(result, row, 5) ? true : false;
  138    m_onStartup = DBGetFieldLong(result, row, 6) ? true : false;
  139    m_creationTime = DBGetFieldLong(result, row, 7);
  140    m_creatorId = DBGetFieldLong(result, row, 8);
  141    m_refCount = 0;
  142 }
  143 
  144 /**
  145  * Create new user agent message
  146  */
  147 UserAgentNotificationItem::UserAgentNotificationItem(const TCHAR *message, const IntegerArray<uint32_t>& objects, time_t startTime, time_t endTime, bool startup, uint32_t userId) : m_objects(objects)
  148 {
  149    m_id = CreateUniqueId(IDG_UA_MESSAGE);
  150    _tcslcpy(m_message, message, MAX_USER_AGENT_MESSAGE_SIZE);
  151    m_startTime = startTime;
  152    m_endTime = endTime;
  153    m_recall = false;
  154    m_onStartup = startup;
  155    m_refCount = 0;
  156    m_creationTime = time(nullptr);
  157    m_creatorId = userId;
  158 }
  159 
  160 /**
  161  * Check if user agent message is applicable on the node
  162  */
  163 bool UserAgentNotificationItem::isApplicable(uint32_t nodeId) const
  164 {
  165    for (int i = 0; i < m_objects.size(); i++)
  166    {
  167       uint32_t id = m_objects.get(i);
  168       if ((id == nodeId) || IsParentObject(id, nodeId))
  169          return true;
  170    }
  171    return false;
  172 }
  173 
  174 /**
  175  * Check if object is node - then send update, if container - iterate over children
  176  */
  177 static void SendUpdate(NXCPMessage *msg, NetObj *object)
  178 {
  179    if (object->getObjectClass() == OBJECT_NODE)
  180    {
  181       if ((static_cast<Node*>(object)->getCapabilities() & NC_HAS_USER_AGENT) == 0)
  182          return;
  183 
  184       shared_ptr<AgentConnectionEx> conn = static_cast<Node *>(object)->getAgentConnection(false);
  185       if (conn != nullptr)
  186       {
  187          msg->setId(conn->generateRequestId());
  188          conn->sendMessage(msg);
  189       }
  190    }
  191    else
  192    {
  193       SharedObjectArray<NetObj> *children = object->getChildren();
  194       for(int i = 0; i < children->size(); i++)
  195       {
  196          SendUpdate(msg, children->get(i));
  197       }
  198       delete children;
  199    }
  200 }
  201 
  202 /**
  203  * Method called on user agent message creation or update(recall)
  204  */
  205 void UserAgentNotificationItem::processUpdate()
  206 {
  207    NXCPMessage msg;
  208    msg.setCode(m_recall ? CMD_RECALL_UA_NOTIFICATION : CMD_ADD_UA_NOTIFICATION);
  209    fillMessage(VID_UA_NOTIFICATION_BASE, &msg, false);
  210 
  211    //create and fill message
  212    for (int i = 0; i < m_objects.size(); i++)
  213    {
  214       shared_ptr<NetObj> object = FindObjectById(m_objects.get(i));
  215       if (object != nullptr)
  216          SendUpdate(&msg, object.get());
  217    }
  218 
  219    saveToDatabase();
  220    decRefCount();
  221 }
  222 
  223 /**
  224  * Fill message with user agent message data
  225  */
  226 void UserAgentNotificationItem::fillMessage(UINT32 base, NXCPMessage *msg, bool fullInfo) const
  227 {
  228    msg->setField(base, m_id);
  229    msg->setField(base + 1, m_message);
  230    msg->setFieldFromTime(base + 2, m_startTime);
  231    msg->setFieldFromTime(base + 3, m_endTime);
  232    msg->setField(base + 4, m_onStartup);
  233    if (fullInfo) // do not send info to agent
  234    {
  235       msg->setFieldFromInt32Array(base + 5, &m_objects);
  236       msg->setField(base + 6, m_recall);
  237       msg->setFieldFromTime(base + 7, m_creationTime);
  238       msg->setField(base + 8, m_creatorId);
  239    }
  240 }
  241 
  242 /**
  243  * Save object to database
  244  */
  245 void UserAgentNotificationItem::saveToDatabase()
  246 {
  247    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
  248 
  249    static const TCHAR *columns[] = {
  250       _T("message"), _T("objects"), _T("start_time"), _T("end_time"), _T("recall"), _T("on_startup"),
  251       _T("creation_time"),  _T("created_by"),  nullptr
  252    };
  253 
  254    DB_STATEMENT hStmt = DBPrepareMerge(hdb, _T("user_agent_notifications"), _T("id"), m_id, columns);
  255    if (hStmt != nullptr)
  256    {
  257       DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_message, MAX_USER_AGENT_MESSAGE_SIZE);
  258 
  259       StringBuffer buffer;
  260       for(int i = 0; i < m_objects.size(); i++)
  261       {
  262          if (buffer.length() > 0)
  263             buffer.append(_T(','));
  264          buffer.append(m_objects.get(i));
  265       }
  266       DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, buffer, MAX_USER_AGENT_MESSAGE_SIZE);
  267       DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, static_cast<uint32_t>(m_startTime));
  268       DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, static_cast<uint32_t>(m_endTime));
  269       DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, (m_recall ? _T("1") : _T("0")), DB_BIND_STATIC);
  270       DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, (m_onStartup ? _T("1") : _T("0")), DB_BIND_STATIC);
  271       DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, static_cast<uint32_t>(m_creationTime));
  272       DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_creatorId);
  273       DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_id);
  274 
  275       DBExecute(hStmt);
  276       DBFreeStatement(hStmt);
  277    }
  278 
  279    DBConnectionPoolReleaseConnection(hdb);
  280 }
  281 
  282 /**
  283  * Serealize object to json
  284  */
  285 json_t *UserAgentNotificationItem::toJson() const
  286 {
  287    json_t *root = json_object();
  288    json_object_set_new(root, "id", json_integer(m_id));
  289    json_object_set_new(root, "message", json_string_t(m_message));
  290    json_object_set_new(root, "objectList", m_objects.toJson());
  291    json_object_set_new(root, "startTime", json_integer(m_startTime));
  292    json_object_set_new(root, "endTime", json_integer(m_endTime));
  293    json_object_set_new(root, "recalled", json_boolean(m_recall));
  294    json_object_set_new(root, "creationTime", json_boolean(m_creationTime));
  295    json_object_set_new(root, "createdBy", json_boolean(m_creatorId));
  296    return root;
  297 }