#include <internal/facts/aix/memory_resolver.hpp> #include <internal/util/aix/odm.hpp> #include <leatherman/logging/logging.hpp> #include <sys/vminfo.h> #include <sys/cfgodm.h> #include <sys/limits.h> #include <system_error> using namespace std; using namespace facter::util::aix; // This routine is useful to encapsulate knowledge of the PAGE_SIZE // in one place and to also handle implicit conversions of numeric // values to uint64_t, which is what we use to represent bytes. Otherwise, // we risk accidentally capturing an overflowed value in our computed // memory facts. static uint64_t pages_to_bytes(uint64_t num_pages) { return num_pages * PAGE_SIZE; } namespace facter { namespace facts { namespace aix { memory_resolver::data memory_resolver::collect_data(collection& facts) { data result; vminfo info; auto res = vmgetinfo(&info, VMINFO, sizeof(info)); if (res < 0) { throw system_error(errno, system_category()); } result.mem_total = pages_to_bytes(info.memsizepgs); result.mem_free = pages_to_bytes(info.numfrb); auto cu_at_query = odm_class<CuAt>::open("CuAt").query("value=paging and attribute=type"); for (auto& cu_at : cu_at_query) { string device = string("/dev/") + cu_at.name; pginfo info; auto res = swapqry(const_cast<char*>(device.c_str()), &info); if (res < 0) { // it's really hard to tell from the ODM if a device // is a disk, just by its name. So we'll always try to // swapqry the things that have an attribute we // expect, but ignore any errno values that look like // "this just wasn't a good device to query" // ENXIO: No such device address. if (errno != ENODEV && errno != ENOENT && errno != ENOTBLK && errno != ENXIO) { throw system_error(errno, system_category(), device); } else { LOG_DEBUG("cannot use device {1}: error is {2}", device, errno); } } result.swap_total += pages_to_bytes(info.size); result.swap_free += pages_to_bytes(info.free); } return result; } }}} // namespace facter::facts::aix