From 76090c2b1952fb04adffd16abe35bd2ef684b461 Mon Sep 17 00:00:00 2001 From: arjen Date: Fri, 21 Feb 2003 08:08:05 +0000 Subject: [PATCH] Gcm_input also detects packages that are removed from the system. Determining the version number of a package in a RPM list is improved. Only the last one or two parts of the string that begin with a '-' and a number are considered the version. --- src/gcm_input/message.cpp | 200 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 168 insertions(+), 32 deletions(-) diff --git a/src/gcm_input/message.cpp b/src/gcm_input/message.cpp index 4d5b962..96214b5 100644 --- a/src/gcm_input/message.cpp +++ b/src/gcm_input/message.cpp @@ -8,7 +8,7 @@ *********************** ** FILE NAME : message.cpp ** SYSTEM NAME : Gnucomo - Gnu Computer Monitoring -** VERSION NUMBER : $Revision: 1.6 $ +** VERSION NUMBER : $Revision: 1.7 $ ** ** DESCRIPTION : Implementation of the message handling classes ** @@ -20,13 +20,19 @@ ******************************** ** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl ** CREATION DATE : Sep 16, 2002 -** LAST UPDATE : Jan 31, 2003 +** LAST UPDATE : Feb 19, 2003 ** MODIFICATIONS : **************************************************************************/ /***************************** $Log: message.cpp,v $ - Revision 1.6 2003-02-05 09:37:51 arjen + Revision 1.7 2003-02-21 08:08:05 arjen + Gcm_input also detects packages that are removed from the system. + Determining the version number of a package in a RPM + list is improved. Only the last one or two parts of the string that + begin with a '-' and a number are considered the version. + + Revision 1.6 2003/02/05 09:37:51 arjen Create notifications when a new package is discovered in a 'rpm -qa' list or when the version of a package is changed. @@ -48,8 +54,9 @@ *****************************/ -static const char *RCSID = "$Id: message.cpp,v 1.6 2003-02-05 09:37:51 arjen Exp $"; +static const char *RCSID = "$Id: message.cpp,v 1.7 2003-02-21 08:08:05 arjen Exp $"; +#include #include "message.h" extern bool verbose; /* Defined in the main application */ @@ -88,7 +95,7 @@ bool operator >> (message_buffer &b, String &s) b.buffer.push_back(l); // next_line keeps pointing to the end. - + s = l; input_ok = true; } @@ -281,7 +288,7 @@ double client_message::classify(String host, UTC arriv, String serv) ** VARS CHANGED : ** FUNCTIONS USED : ** SEE ALSO : -** LAST MODIFIED : Jan 31, 2003 +** LAST MODIFIED : Feb 19, 2003 **========================================================================= */ @@ -289,9 +296,13 @@ int client_message::enter() { long nr_lines = 0; String line; + String qry; String change_notification(""); String create_notification(""); + bool initial_entry = false; + + std::list packages; /* Double-check the classification of the message */ @@ -304,7 +315,7 @@ int client_message::enter() if (mail_header) { // Skip the mail header. - + while (input >> line && line != ""); } @@ -323,6 +334,27 @@ int client_message::enter() std::cout << "Object id for " << hostname << " is " << objectid << "\n"; } + if (classification == RPMLIST) + { + + int n_packages; + + /* Read all packages, so we will know which ones are */ + /* missing at the end. */ + + qry = "select name from parameter where objectid='"; + qry += objectid + "' and class='package'"; + n_packages = database.Query(qry); + initial_entry = n_packages == 0; + + std::cout << n_packages << " packages in database.\n"; + for (int t = 0; t < n_packages; t++) + { + packages.push_back(database.Field(t, "name")); + } + std::cout << "Package list built: " << packages.size() << ".\n"; + } + /* Scan the input line by line, entring records into the database */ String rest; // Rest of the line to be parsed @@ -411,7 +443,7 @@ int client_message::enter() insertion += "'" + arrival.format("%Y-%m-%d %T") + "',"; insertion += "'" + SQL_Escape(line) + "',FALSE"; insertion += ")"; - + if (testmode) { std::cout << insertion << "\n"; @@ -451,7 +483,7 @@ int client_message::enter() insertion += "'" + arrival.format("%Y-%m-%d %T") + "',"; insertion += "'" + SQL_Escape(line) + "',FALSE"; insertion += ")"; - + if (testmode) { std::cout << insertion << "\n"; @@ -485,7 +517,7 @@ int client_message::enter() insertion += "'" + arrival.format("%Y-%m-%d %T") + "',"; insertion += "'" + SQL_Escape(line) + "',FALSE"; insertion += ")"; - + if (testmode) { std::cout << insertion << "\n"; @@ -505,28 +537,39 @@ int client_message::enter() case RPMLIST: // Scan a list of packages and versions from "rpm -a". - // A similar listing can be created on IRIX 6.5 by using the - // command "showprods -3 -n|awk '{printf "%s-%s\n",$2,$3}'|grep -v '^[-=]' \ - // |grep -v Version-Description". - // + // A similar listing can be created on IRIX 6.5 by using the + // command "showprods -3 -n|awk '{printf "%s-%s\n",$2,$3}'|grep -v '^[-=]' \ + // |grep -v Version-Description". + // // We have to separate the package name and the version. // The separation is marked by a '-', followed by a digit. - - String qry = "select count(paramid) from parameter where objectid='"; - qry += objectid + "' and class='package'"; - - database.Query(qry); - long n_packages = String(database.Field(0, "count")); + // However, there may be other sequences of '-'digit in the package name, + // do we have to scan ahead until there is at most one such sequence + // left in the version string. The '-'digit seqeunce inside the + // version usually separates the version and the release number. - bool initial_entry = n_packages == 0; + int version_start, next_version_start; i = line.index('-'); - while (!(line[i] == '-' && isdigit(line[i + 1]))) + version_start = i; + next_version_start = i; + + while (i < ~line - 1) { + while (i < ~line - 1 && !(line[i] == '-' && isdigit(line[i + 1]))) + { + i++; + } + if (i < ~line - 1) + { + version_start = next_version_start; + next_version_start = i; + } i++; } - String package(line(0,i)); - String version(line(i+1, ~line)); + + String package(line(0,version_start)); + String version(line(version_start + 1, ~line)); String paramid; String remark; String insert_h; @@ -545,6 +588,18 @@ int client_message::enter() if (database.Query(qry) == 1) { + std::list::iterator lp; + + lp = find(packages.begin(), packages.end(), package); + if (lp != packages.end()) + { + packages.erase(lp); + } + else + { + std::cerr << "Could NOT find " << package << " in list.\n"; + } + paramid = database.Field(0, "paramid"); qry = "select value from property where paramid='"; qry += paramid + "' and name='version'"; @@ -577,11 +632,18 @@ int client_message::enter() change_notification = database.new_notification(objectid, "property modified", remark); } - insertion = "insert into parameter_notification (notificationid, paramid) values ('"; - insertion += change_notification + "', '"; - insertion += paramid + "')"; + if (change_notification != "") + { + insertion = "insert into parameter_notification (notificationid, paramid) values ('"; + insertion += change_notification + "', '"; + insertion += paramid + "')"; - database.Query(insertion); + database.Query(insertion); + } + else + { + std::cerr << "gcm_input ERROR: Cannot create 'property modified' notification.\n"; + } } else { @@ -640,11 +702,18 @@ int client_message::enter() remark = "Gnucomo detected new parameter(s) of class package"; create_notification = database.new_notification(objectid, "parameter created", remark); } - insertion = "insert into parameter_notification (notificationid, paramid) values ('"; - insertion += create_notification + "', '"; - insertion += paramid + "')"; + if (create_notification != "") + { + insertion = "insert into parameter_notification (notificationid, paramid) values ('"; + insertion += create_notification + "', '"; + insertion += paramid + "')"; - database.Query(insertion); + database.Query(insertion); + } + else + { + std::cerr << "gcm_input ERROR: Cannot create 'parameter created' notification.\n"; + } } } } @@ -665,6 +734,73 @@ int client_message::enter() } } + if (classification == RPMLIST) + { + std::list::iterator lp; + String remove_notification(""); + + /* + * If there are any packages left in the list, they seem to have + * disappeared from the system. + */ + + for (lp = packages.begin(); lp != packages.end(); lp++) + { + String paramid; + String remark; + String insert; + + // Construct a qry to check the package's existance + + qry = "select paramid from parameter where objectid='"; + qry += objectid + "' and class='package' and name='"; + qry += *lp + "'"; + + if (database.Query(qry) == 1) + { + paramid = database.Field(0, "paramid"); + qry ="select change_nature from history where paramid='"; + qry += paramid + "' order by modified desc"; + if (database.Query(qry) <= 0) + { + std::cerr << "Database ERROR: no history record for parameter " << *lp << ".\n"; + } + else if (database.Field(0, "change_nature") != "REMOVED") + { + if (verbose) + { + std::cout << "Removing parameter " << *lp << ".\n"; + } + + insert = "insert into history (paramid, modified, change_nature)"; + insert += " values ('"; + insert += paramid + "', '" + arrival.format("%Y-%m-%d %T") + "', 'REMOVED')"; + + database.Query(insert); + + if (remove_notification == "") + { + remark = "Gnucomo detected that package(s) have disappeared "; + remove_notification = database.new_notification(objectid, "parameter removed", remark); + } + + if (remove_notification != "") + { + insert = "insert into parameter_notification (notificationid, paramid) values ('"; + insert += remove_notification + "', '"; + insert += paramid + "')"; + + database.Query(insert); + } + else + { + std::cerr << "gcm_input ERROR: Cannot create 'parameter removed' notification.\n"; + } + } + } + } + } + if (verbose) { std::cout << nr_lines << " lines parsed from the log file.\n"; -- 2.11.0