The following patch set includes code to report the wordsize of the system's processor, as reported by CPU flags. It also determines the host's binary wordsize by checking the size of a memory address and multiplying it by the size of a single byte.
Also adds a new source module, processor, which contains APIs for retrieve processor details.
Moved the processor initialization code to this new source module.
Signed-off-by: Darryl L. Pierce dpierce@redhat.com --- src/Makefile.am | 10 ++- src/host.cpp | 139 +----------------------------------- src/host.h | 11 +++ src/main.cpp | 3 + src/processor.cpp | 169 ++++++++++++++++++++++++++++++++++++++++++++ src/processor.h | 26 +++++++ src/qmf/processoragent.cpp | 45 ++++++++++++ src/qmf/processoragent.h | 47 ++++++++++++ src/schema-host.xml | 5 ++ 9 files changed, 318 insertions(+), 137 deletions(-) create mode 100644 src/processor.cpp create mode 100644 src/processor.h create mode 100644 src/qmf/processoragent.cpp create mode 100644 src/qmf/processoragent.h
diff --git a/src/Makefile.am b/src/Makefile.am index 304214c..c56a900 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,9 @@ generated_file_list = \ qmf/com/redhat/matahari/host/Host.cpp \ qmf/com/redhat/matahari/host/Host.h \ qmf/com/redhat/matahari/host/Package.cpp \ - qmf/com/redhat/matahari/host/Package.h + qmf/com/redhat/matahari/host/Package.h \ + qmf/com/redhat/matahari/host/Processor.cpp \ + qmf/com/redhat/matahari/host/Processor.h
nodist_matahari_SOURCES = $(generated_file_list) config.h
@@ -24,8 +26,12 @@ matahari_SOURCES = \ host.h \ hostlistener.h \ main.cpp \ + processor.cpp \ + processor.h \ qmf/hostagent.cpp \ - qmf/hostagent.h + qmf/hostagent.h \ + qmf/processoragent.cpp \ + qmf/processoragent.h
SCHEMAS = \ schema-host.xml diff --git a/src/host.cpp b/src/host.cpp index d129121..e653107 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -22,9 +22,8 @@ #include <fstream> #include "host.h" #include <libvirt/libvirt.h> -#include <pcre.h> +#include "processor.h" #include <set> -#include <stdexcept> #include <string> #include <sys/sysinfo.h>
@@ -95,18 +94,6 @@ typedef BOOL (WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
#endif
-typedef struct cpuinfo_ -{ - static bool initialized; - string model; - unsigned int cpus; - unsigned int cores; -} cpuinfo_t; - -bool cpuinfo_t::initialized = false; - -cpuinfo_t cpuinfo; - set<HostListener*> _listeners; unsigned int _heartbeat_sequence;
@@ -286,128 +273,10 @@ host_get_memory() return memory; }
-void -host_get_cpu_details() -{ - if(cpuinfo.initialized) return; - - cpuinfo.initialized = true; - -#if __linux__ - ifstream input("/proc/cpuinfo"); - - if(input.is_open()) - { - string regexstr = "(.*\S)\s*:\s*(\S.*)"; - int expected = 3; - int found[expected * 3]; - const char* pcre_error; - int pcre_error_offset; - pcre* regex; - bool done = false; - bool started = false; - - regex = pcre_compile(regexstr.c_str(), 0, &pcre_error, &pcre_error_offset, NULL); - if(!regex) { throw runtime_error("Unable to compile regular expression."); } - - while(!input.eof()) - { - string line; - - getline(input, line); - int match = pcre_exec(regex, NULL, line.c_str(), line.length(), - 0, PCRE_NOTEMPTY,found, expected * 3); - - if(match == expected) - { - string name = line.substr(found[2], found[3] - found[2]); - string value = line.substr(found[4], found[5] - found[4]); - - /* If we're at a second processor and we've already started, - then we're done. - */ - if (name == "processor") - { - cpuinfo.cpus++; - if (started) - { - done = true; - } - else - { - started = true; - } - } - else if (!done) - { - if (name == "cpu cores") cpuinfo.cores = atoi(value.c_str()); - else if (name == "model name") cpuinfo.model = value; - } - } - } - input.close(); - cpuinfo.cpus /= cpuinfo.cores; - } -#elif defined WIN32 - LPFN_GLPI proc; - DWORD ret_length; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer, ptr; - - proc = (LPFN_GLPI) GetProcAddress(GetModuleHandle(TEXT("kernel32")), - "GetLogicalProcessorInformation"); - if(proc) - { - BOOL done = FALSE; - - while (!done) - { - DWORD rc = proc(buffer, &ret_length); - - if(rc == FALSE) - { - if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - if(buffer) - { - free(buffer); - buffer = NULL; - } - - buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(ret_length); - } - } - else - { - done = TRUE; - } - } - - ptr = buffer; - - DWORD offset = 0; - - while(offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= ret_length) - { - switch(ptr->Relationship) - { - case RelationProcessorCore: cpuinfo.cores++; break; - case RelationProcessorPackage: cpuinfo.cpus++; break; - } - } - - if(buffer) - { - free(buffer); - buffer = NULL; - } - } -#endif -} - string host_get_cpu_model() { - host_get_cpu_details(); + cpu_get_details();
return cpuinfo.model; } @@ -415,7 +284,7 @@ host_get_cpu_model() unsigned int host_get_number_of_cpus() { - host_get_cpu_details(); + cpu_get_details();
return cpuinfo.cpus; } @@ -423,7 +292,7 @@ host_get_number_of_cpus() unsigned int host_get_number_of_cpu_cores() { - host_get_cpu_details(); + cpu_get_details();
return cpuinfo.cores; } diff --git a/src/host.h b/src/host.h index 574e8b5..b6e9ffb 100644 --- a/src/host.h +++ b/src/host.h @@ -27,6 +27,17 @@
using namespace std;
+typedef struct cpuinfo_ +{ + static bool initialized; + string model; + unsigned int cpus; + unsigned int cores; + unsigned int wordsize; +} cpuinfo_t; + +extern cpuinfo_t cpuinfo; + void host_register_listener(HostListener* listener);
void host_remove_istener(HostListener* listener); diff --git a/src/main.cpp b/src/main.cpp index f7d6329..c75d0ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,7 @@ #include "host.h"
#include "qmf/hostagent.h" +#include "qmf/processoragent.h"
#include "qmf/com/redhat/matahari/host/Package.h"
@@ -81,6 +82,7 @@ main(int argc, char **argv) ConnectionSettings settings; ManagementAgent *agent; HostAgent hostAgent; + ProcessorAgent processorAgent;
struct option opt[] = { {"help", no_argument, NULL, 'h'}, @@ -183,6 +185,7 @@ main(int argc, char **argv)
// Get the info and post it to the broker hostAgent.setup(agent); + processorAgent.setup(agent, hostAgent);
while(1) { diff --git a/src/processor.cpp b/src/processor.cpp new file mode 100644 index 0000000..bc72757 --- /dev/null +++ b/src/processor.cpp @@ -0,0 +1,169 @@ +/* processor.cpp - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include "config.h" +#include <fstream> +#include "host.h" +#include <limits.h> +#include <pcre.h> +#include "processor.h" +#include <stdexcept> + +cpuinfo_t cpuinfo; +bool cpuinfo_t::initialized = false; + +void +cpu_get_details() +{ + if(cpuinfo.initialized) return; + + cpuinfo.initialized = true; + +#if __linux__ + ifstream input("/proc/cpuinfo"); + + if(input.is_open()) + { + string regexstr = "(.*\S)\s*:\s*(\S.*)"; + int expected = 3; + int found[expected * 3]; + const char* pcre_error; + int pcre_error_offset; + pcre* regex; + bool done = false; + bool started = false; + + regex = pcre_compile(regexstr.c_str(), 0, &pcre_error, &pcre_error_offset, NULL); + if(!regex) { throw runtime_error("Unable to compile regular expression."); } + + while(!input.eof()) + { + string line; + + getline(input, line); + int match = pcre_exec(regex, NULL, line.c_str(), line.length(), + 0, PCRE_NOTEMPTY,found, expected * 3); + + if(match == expected) + { + string name = line.substr(found[2], found[3] - found[2]); + string value = line.substr(found[4], found[5] - found[4]); + + /* If we're at a second processor and we've already started, + then we're done. + */ + if (name == "processor") + { + cpuinfo.cpus++; + if (started) + { + done = true; + } + else + { + started = true; + } + } + else if (!done) + { + if (name == "cpu cores") cpuinfo.cores = atoi(value.c_str()); + else if (name == "model name") cpuinfo.model = value; + else if (name == "flags") + { + string flags(value); + + // if the cpuflags contain "lm" then it's a 64 bit CPU + // http://www.brandonhutchinson.com/Understanding_proc_cpuinfo.html + cpuinfo.wordsize = (flags.find(" lm ") ? 64 : 32); + } + } + } + } + input.close(); + cpuinfo.cpus /= cpuinfo.cores; + } +#elif defined WIN32 + LPFN_GLPI proc; + DWORD ret_length; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer, ptr; + + proc = (LPFN_GLPI) GetProcAddress(GetModuleHandle(TEXT("kernel32")), + "GetLogicalProcessorInformation"); + if(proc) + { + BOOL done = FALSE; + + while (!done) + { + DWORD rc = proc(buffer, &ret_length); + + if(rc == FALSE) + { + if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + if(buffer) + { + free(buffer); + buffer = NULL; + } + + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(ret_length); + } + } + else + { + done = TRUE; + } + } + + ptr = buffer; + + DWORD offset = 0; + + while(offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= ret_length) + { + switch(ptr->Relationship) + { + case RelationProcessorCore: cpuinfo.cores++; break; + case RelationProcessorPackage: cpuinfo.cpus++; break; + } + } + + if(buffer) + { + free(buffer); + buffer = NULL; + } + } +#endif +} + +unsigned int +cpu_get_wordsize() +{ + static unsigned int wordsize = 0; + + if(wordsize == 0) + { + cpu_get_details(); + return cpuinfo.wordsize; + } + + return wordsize; +} diff --git a/src/processor.h b/src/processor.h new file mode 100644 index 0000000..f56f177 --- /dev/null +++ b/src/processor.h @@ -0,0 +1,26 @@ +#ifndef __PROCESSOR_H +#define __PROCESSOR_H + +/* processor.h - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +void cpu_get_details(); +unsigned int cpu_get_wordsize(); + +#endif diff --git a/src/qmf/processoragent.cpp b/src/qmf/processoragent.cpp new file mode 100644 index 0000000..7c0d6ec --- /dev/null +++ b/src/qmf/processoragent.cpp @@ -0,0 +1,45 @@ +/* processoragent.cpp - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include "config.h" +#include "processoragent.h" +#include "processor.h" + +ProcessorAgent::ProcessorAgent() +{ } + +ProcessorAgent::~ProcessorAgent() +{ } + +void +ProcessorAgent::setup(ManagementAgent* agent, HostAgent& parent) +{ + this->_agent = agent; + this->_management_object = new _qmf::Processor(agent, this); + agent->addObject(this->_management_object); + + _management_object->set_host(parent.GetManagementObject()->getObjectId()); + _management_object->set_wordsize(cpu_get_wordsize()); +} + +ManagementObject* +ProcessorAgent::GetManagementObject() const +{ + return this->_management_object; +} diff --git a/src/qmf/processoragent.h b/src/qmf/processoragent.h new file mode 100644 index 0000000..08d6090 --- /dev/null +++ b/src/qmf/processoragent.h @@ -0,0 +1,47 @@ +#ifndef __PROCESSORAGENT_H +#define __PROCESSORAGENT_H + +/* processoragent.h - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include <qpid/agent/ManagementAgent.h> +#include <qpid/management/Manageable.h> + +#include "qmf/hostagent.h" +#include "qmf/com/redhat/matahari/host/Processor.h" + +using namespace qpid::management; + +namespace _qmf = qmf::com::redhat::matahari::host; + +class ProcessorAgent : public Manageable +{ + private: + _qmf::Processor* _management_object; + ManagementAgent* _agent; + + public: + ProcessorAgent(); + virtual ~ProcessorAgent(); + + void setup(ManagementAgent* agent, HostAgent& parent); + ManagementObject* GetManagementObject() const; +}; + +#endif diff --git a/src/schema-host.xml b/src/schema-host.xml index 7a223f9..e5253a5 100644 --- a/src/schema-host.xml +++ b/src/schema-host.xml @@ -25,7 +25,12 @@ <method name="identify" desc="Tells the host to beep its pc speaker." /> <method name="shutdown" desc="Shutdown node" /> <method name="reboot" desc="Reboot node" /> + </class>
+ <class name="Processor"> + <!-- properties --> + <property name="host" type="objId" access="RO" desc="The host agent." /> + <property name="wordsize" type="uint8" access="RO" desc="The wordsize for the processor." /> </class>
<eventArguments>
The platform specifies the binary wordsize for a Host system. So for a 64 bit installation, this will return 64. If it's a 32 bit installation on a 64 bit system, it will return 32.
Signed-off-by: Darryl L. Pierce dpierce@redhat.com --- src/host.cpp | 14 ++++++++++++++ src/host.h | 2 ++ src/qmf/hostagent.cpp | 1 + src/schema-host.xml | 2 +- 4 files changed, 18 insertions(+), 1 deletions(-)
diff --git a/src/host.cpp b/src/host.cpp index e653107..cdf47e9 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -22,6 +22,7 @@ #include <fstream> #include "host.h" #include <libvirt/libvirt.h> +#include <limits.h> #include "processor.h" #include <set> #include <string> @@ -217,6 +218,19 @@ host_get_hypervisor() return hypervisor; }
+unsigned int +host_get_platform() +{ + static unsigned int wordsize = 0; + + if(wordsize == 0) + { + wordsize = sizeof(void *) * CHAR_BIT; + } + + return wordsize; +} + string host_get_architecture() { diff --git a/src/host.h b/src/host.h index b6e9ffb..e1dd02b 100644 --- a/src/host.h +++ b/src/host.h @@ -50,6 +50,8 @@ string host_get_hostname();
string host_get_hypervisor();
+unsigned int host_get_platform(); + string host_get_architecture();
unsigned int host_get_memory(); diff --git a/src/qmf/hostagent.cpp b/src/qmf/hostagent.cpp index 350323f..c9c18f7 100644 --- a/src/qmf/hostagent.cpp +++ b/src/qmf/hostagent.cpp @@ -43,6 +43,7 @@ HostAgent::setup(ManagementAgent* agent) _management_object->set_uuid(host_get_uuid()); _management_object->set_hostname(host_get_hostname()); _management_object->set_hypervisor(host_get_hypervisor()); + _management_object->set_platform(host_get_platform()); _management_object->set_arch(host_get_architecture()); _management_object->set_memory(host_get_memory());
diff --git a/src/schema-host.xml b/src/schema-host.xml index e5253a5..2c6e52e 100644 --- a/src/schema-host.xml +++ b/src/schema-host.xml @@ -9,7 +9,7 @@ <property name="memory" type="int64" access="RO" desc="Amount of primary memory for host (kb)" unit="kb" /> <property name="arch" type="sstr" access="RO" desc="Architecture of host" /> <property name="hypervisor" type="sstr" access="RO" desc="Hypervisor used by host" /> - <property name="platform" type="sstr" access="RO" desc="The wordsize for the host." /> + <property name="platform" type="uint8" access="RO" desc="The wordsize for the host." /> <property name="cpu_model" type="lstr" access="RO" desc="The process model description." /> <property name="cpu_count" type="uint8" access="RO" desc="The number of physical CPUs." /> <property name="cpu_cores" type="uint8" access="RO" desc="The total number of processor cores." />
On Fri, Jul 30, 2010 at 05:23:46PM -0400, Darryl L. Pierce wrote:
The following patch set includes code to report the wordsize of the system's processor, as reported by CPU flags. It also determines the host's binary wordsize by checking the size of a memory address and multiplying it by the size of a single byte.
This is pushed upstream.
matahari@lists.fedorahosted.org