"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.4.178/src/server/core/alarm_category.cpp" (16 Jun 2020, 11251 Bytes) of package /linux/misc/netxms-3.4.178.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 "alarm_category.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.3.350_vs_3.4.178.

    1 /*
    2 ** NetXMS - Network Management System
    3 ** Copyright (C) 2016-2020 RadenSolutions
    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: alarm_category.cpp
   20 **
   21 **/
   22 
   23 #include "nxcore.h"
   24 
   25 /**
   26  * Create new category
   27  */
   28 AlarmCategory::AlarmCategory(UINT32 id)
   29 {
   30    m_id = id;
   31    m_name = NULL;
   32    m_description = NULL;
   33 }
   34 
   35 /**
   36  * Create category from DB record
   37  */
   38 AlarmCategory::AlarmCategory(DB_RESULT hResult, int row, IntegerArray<UINT32> *aclCache)
   39 {
   40    m_id = DBGetFieldULong(hResult, row, 0);
   41    m_name = DBGetField(hResult, row, 1, NULL, 0);
   42    m_description = DBGetField(hResult, row, 2, NULL, 0);
   43 
   44    int i = 0;
   45    while((i < aclCache->size()) && (aclCache->get(i) != m_id))
   46       i += 2;
   47    while((i < aclCache->size()) && (aclCache->get(i) == m_id))
   48    {
   49       m_acl.add(aclCache->get(i + 1));
   50       i += 2;
   51    }
   52 }
   53 
   54 /**
   55  * Create new category
   56  */
   57 AlarmCategory::AlarmCategory(UINT32 id, const TCHAR *name, const TCHAR *description)
   58 {
   59    m_id = id;
   60    m_name = MemCopyString(name);
   61    m_description = MemCopyString(description);
   62 }
   63 
   64 /**
   65  * Copy constructor
   66  */
   67 AlarmCategory::AlarmCategory(AlarmCategory* obj)
   68 {
   69    m_id = obj->m_id;
   70    m_name = MemCopyString(obj->m_name);
   71    m_description = MemCopyString(obj->m_description);
   72 }
   73 
   74 /**
   75  * Destructor
   76  */
   77 AlarmCategory::~AlarmCategory()
   78 {
   79    MemFree(m_name);
   80    MemFree(m_description);
   81 }
   82 
   83 /**
   84  * Fill message with alarm category data
   85  */
   86 void AlarmCategory::fillMessage(NXCPMessage *msg, UINT32 baseId) const
   87 {
   88    msg->setField(baseId, m_id);
   89    msg->setField(baseId + 1, m_name);
   90    msg->setField(baseId + 2, m_description);
   91    msg->setFieldFromInt32Array(baseId + 3, &m_acl);
   92 }
   93 
   94 /**
   95  * Modify category from NXCP message
   96  */
   97 void AlarmCategory::modifyFromMessage(const NXCPMessage *msg)
   98 {
   99    MemFree(m_name);
  100    m_name = msg->getFieldAsString(VID_NAME);
  101 
  102    MemFree(m_description);
  103    m_description = msg->getFieldAsString(VID_DESCRIPTION);
  104 
  105    msg->getFieldAsInt32Array(VID_ALARM_CATEGORY_ACL, &m_acl);
  106 }
  107 
  108 /**
  109  * Save category to database
  110  */
  111 bool AlarmCategory::saveToDatabase() const
  112 {
  113    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
  114 
  115    bool success = DBBegin(hdb);
  116    if (success)
  117    {
  118       DB_STATEMENT hStmt;
  119       if (IsDatabaseRecordExist(hdb, _T("alarm_categories"), _T("id"), m_id))
  120          hStmt = DBPrepare(hdb, _T("UPDATE alarm_categories SET name=?,descr=? WHERE id=?"));
  121       else
  122          hStmt = DBPrepare(hdb, _T("INSERT INTO alarm_categories (name,descr,id) VALUES (?,?,?)"));
  123       if (hStmt != NULL)
  124       {
  125          DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_name, DB_BIND_STATIC);
  126          DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_description, DB_BIND_STATIC);
  127          DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, m_id);
  128          success = DBExecute(hStmt);
  129          DBFreeStatement(hStmt);
  130       }
  131 
  132       if (success)
  133       {
  134          hStmt = DBPrepare(hdb, _T("DELETE FROM alarm_category_acl WHERE category_id=?"));
  135          if (hStmt != NULL)
  136          {
  137             DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
  138             success = DBExecute(hStmt);
  139             DBFreeStatement(hStmt);
  140          }
  141          else
  142          {
  143             success = false;
  144          }
  145       }
  146 
  147       if (success)
  148       {
  149          hStmt = DBPrepare(hdb, _T("INSERT INTO alarm_category_acl (category_id,user_id) VALUES (?,?)"));
  150          if (hStmt != NULL)
  151          {
  152             DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
  153             for(int i = 0; (i < m_acl.size()) && success; i++)
  154             {
  155                DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, m_acl.get(i));
  156                success = DBExecute(hStmt);
  157             }
  158             DBFreeStatement(hStmt);
  159          }
  160       }
  161 
  162       if (success)
  163          success = DBCommit(hdb);
  164       else
  165          DBRollback(hdb);
  166    }
  167 
  168    DBConnectionPoolReleaseConnection(hdb);
  169    return success;
  170 }
  171 
  172 bool AlarmCategory::checkAccess(UINT32 userId)
  173 {
  174    for(int i = 0; i < m_acl.size(); i++)
  175    {
  176       if (((m_acl.get(i) & GROUP_FLAG) && CheckUserMembership(userId, m_acl.get(i))) || (m_acl.get(i) == userId))
  177          return true;
  178    }
  179    return false;
  180 }
  181 
  182 /**
  183  * Alarm categories
  184  */
  185 static HashMap<UINT32, AlarmCategory> s_categories(Ownership::True);
  186 static RWLock s_lock;
  187 
  188 /**
  189  * Callback for sending alarm category configuration change notifications
  190  */
  191 static void SendAlarmCategoryDBChangeNotification(ClientSession *session, void *arg)
  192 {
  193    if (session->isAuthenticated())
  194       session->postMessage((NXCPMessage *)arg);
  195 }
  196 
  197 /**
  198  * Get alarm categories from database
  199  */
  200 void GetAlarmCategories(NXCPMessage *msg)
  201 {
  202    s_lock.readLock();
  203    msg->setField(VID_NUM_ELEMENTS, s_categories.size());
  204    UINT32 fieldId = VID_ELEMENT_LIST_BASE;
  205    Iterator<AlarmCategory> *it = s_categories.iterator();
  206    while(it->hasNext())
  207    {
  208       AlarmCategory *c = it->next();
  209       c->fillMessage(msg, fieldId);
  210       fieldId += 10;
  211    }
  212    delete it;
  213    s_lock.unlock();
  214 }
  215 
  216 /**
  217 * Update alarm category database
  218 */
  219 uint32_t UpdateAlarmCategory(const NXCPMessage *request, uint32_t *returnId)
  220 {
  221    TCHAR name[64];
  222    request->getFieldAsString(VID_NAME, name, 64);
  223    if (name[0] == 0)
  224       return RCC_CATEGORY_NAME_EMPTY;
  225 
  226    uint32_t id = request->getFieldAsUInt32(VID_CATEGORY_ID);
  227 
  228    AlarmCategory *category;
  229    s_lock.writeLock();
  230    if (id == 0)
  231    {
  232       id = CreateUniqueId(IDG_ALARM_CATEGORY);
  233       category = new AlarmCategory(id);
  234       s_categories.set(id, category);
  235    }
  236    else
  237    {
  238       category = s_categories.get(id);
  239       if (category == nullptr)
  240       {
  241          s_lock.unlock();
  242          return RCC_INVALID_OBJECT_ID;
  243       }
  244    }
  245    *returnId = id;
  246    category->modifyFromMessage(request);
  247    UINT32 rcc = category->saveToDatabase() ? RCC_SUCCESS : RCC_DB_FAILURE;
  248 
  249    // Notify client for DB change
  250    if (rcc == RCC_SUCCESS)
  251    {
  252       NXCPMessage msg;
  253       msg.setCode(CMD_ALARM_CATEGORY_UPDATE);
  254       msg.setField(VID_NOTIFICATION_CODE, (UINT16)NX_NOTIFY_ALARM_CATEGORY_UPDATE);
  255       category->fillMessage(&msg, VID_ELEMENT_LIST_BASE);
  256       EnumerateClientSessions(SendAlarmCategoryDBChangeNotification, &msg);
  257    }
  258 
  259    s_lock.unlock();
  260    return rcc;
  261 }
  262 
  263 /**
  264 * Delete alarm category from database
  265 */
  266 uint32_t DeleteAlarmCategory(uint32_t id)
  267 {
  268    uint32_t rcc;
  269    s_lock.readLock();
  270    if (s_categories.contains(id))
  271    {
  272       s_lock.unlock();
  273 
  274       DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
  275       bool success = DBBegin(hdb);
  276       if (success)
  277       {
  278          DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM alarm_categories WHERE id=?"));
  279          if (hStmt != NULL)
  280          {
  281             DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
  282             success = DBExecute(hStmt);
  283             DBFreeStatement(hStmt);
  284          }
  285          else
  286          {
  287             success = false;
  288          }
  289 
  290          if (success)
  291          {
  292             hStmt = DBPrepare(hdb, _T("DELETE FROM alarm_category_acl WHERE category_id=?"));
  293             if (hStmt != NULL)
  294             {
  295                DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
  296                success = DBExecute(hStmt);
  297                DBFreeStatement(hStmt);
  298             }
  299             else
  300             {
  301                success = false;
  302             }
  303          }
  304 
  305          if (success)
  306          {
  307             success = DBCommit(hdb);
  308             if (success)
  309             {
  310                s_lock.writeLock();
  311                s_categories.remove(id);
  312                s_lock.unlock();
  313 
  314                NXCPMessage nmsg;
  315                nmsg.setCode(CMD_ALARM_CATEGORY_UPDATE);
  316                nmsg.setField(VID_NOTIFICATION_CODE, (UINT16)NX_NOTIFY_ALARM_CATEGORY_DELETE);
  317                nmsg.setField(VID_ELEMENT_LIST_BASE, id);
  318                EnumerateClientSessions(SendAlarmCategoryDBChangeNotification, &nmsg);
  319             }
  320          }
  321          else
  322          {
  323             DBRollback(hdb);
  324          }
  325       }
  326       DBConnectionPoolReleaseConnection(hdb);
  327       rcc = success ? RCC_SUCCESS : RCC_DB_FAILURE;
  328    }
  329    else
  330    {
  331       s_lock.unlock();
  332       rcc = RCC_INVALID_OBJECT_ID;
  333    }
  334    return rcc;
  335 }
  336 
  337 /**
  338  * Check user access to alarm category
  339  */
  340 bool CheckAlarmCategoryAccess(uint32_t userId, uint32_t categoryId)
  341 {
  342    bool result = false;
  343    s_lock.readLock();
  344    AlarmCategory *c = s_categories.get(categoryId);
  345    if (c != nullptr)
  346    {
  347       result = c->checkAccess(userId);
  348    }
  349    s_lock.unlock();
  350    return result;
  351 }
  352 
  353 /**
  354  * Load alarm categories
  355  */
  356 void LoadAlarmCategories()
  357 {
  358    DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
  359 
  360    IntegerArray<UINT32> aclCache(256, 256);
  361    DB_RESULT hResult = DBSelect(hdb, _T("SELECT category_id,user_id FROM alarm_category_acl ORDER BY category_id"));
  362    if (hResult != NULL)
  363    {
  364       int count = DBGetNumRows(hResult);
  365       for(int i = 0; i < count; i++)
  366       {
  367          aclCache.add(DBGetFieldULong(hResult, i, 0));
  368          aclCache.add(DBGetFieldULong(hResult, i, 1));
  369       }
  370       DBFreeResult(hResult);
  371    }
  372 
  373    hResult = DBSelect(hdb, _T("SELECT id,name,descr FROM alarm_categories"));
  374    if (hResult != NULL)
  375    {
  376       int numRows = DBGetNumRows(hResult);
  377       s_lock.writeLock();
  378       s_categories.clear();
  379       for(int i = 0; i < numRows; i++)
  380       {
  381          AlarmCategory *c = new AlarmCategory(hResult, i, &aclCache);
  382          s_categories.set(c->getId(), c);
  383       }
  384       s_lock.unlock();
  385       DBFreeResult(hResult);
  386    }
  387    DBConnectionPoolReleaseConnection(hdb);
  388 }
  389 
  390 AlarmCategory *GetAlarmCategory(uint32_t id)
  391 {
  392    s_lock.readLock();
  393    AlarmCategory *alarmCategory = new AlarmCategory(s_categories.get(id));
  394    s_lock.unlock();
  395    return alarmCategory;
  396 }
  397 
  398 uint32_t GetAndUpdateAlarmCategoryByName(const TCHAR *name, const TCHAR *description)
  399 {
  400    uint32_t id = 0;
  401    s_lock.readLock();
  402    Iterator<AlarmCategory> *it = s_categories.iterator();
  403    while(it->hasNext())
  404    {
  405      AlarmCategory *c = it->next();
  406      if(!_tcscmp(c->getName(), name))
  407      {
  408         c->updateDescription(description);
  409         id = c->getId();
  410         break;
  411      }
  412    }
  413    delete it;
  414    s_lock.unlock();
  415    return id;
  416 }
  417 
  418 uint32_t CreateNewAlarmCategoryFromImport(const TCHAR *name, const TCHAR *description)
  419 {
  420    UINT32 id = CreateUniqueId(IDG_ALARM_CATEGORY);
  421    AlarmCategory *category = new AlarmCategory(id, name, description);
  422 
  423    s_lock.writeLock();
  424    s_categories.set(id, category);
  425    category->saveToDatabase();
  426 
  427    //Notify clients
  428    NXCPMessage msg;
  429    msg.setCode(CMD_ALARM_CATEGORY_UPDATE);
  430    msg.setField(VID_NOTIFICATION_CODE, (UINT16)NX_NOTIFY_ALARM_CATEGORY_UPDATE);
  431    category->fillMessage(&msg, VID_ELEMENT_LIST_BASE);
  432    EnumerateClientSessions(SendAlarmCategoryDBChangeNotification, &msg);
  433 
  434    s_lock.unlock();
  435    return id;
  436 }