The R-tree appears to split the nodes properly, but a basic search fails . . .
[aesalon.git] / src / monitor / SHMReader.cpp
blob46c2f03f9bc318bd129ab8eca3cf2388562c48ce
1 /** Aesalon, a tool to visualize program behaviour in real time.
2 Copyright (C) 2009-2011, Aesalon development team.
4 Aesalon is distributed under the terms of the GNU GPLv3. See
5 the included file LICENSE for more information.
7 @file src/monitor/SHMReader.cpp
8 */
10 #include <semaphore.h>
11 #include <sys/mman.h>
12 #include <fcntl.h>
13 #include <cstring>
14 #include <errno.h>
16 #include "Config.h"
18 #include "monitor/SHMReader.h"
19 #include "monitor/Coordinator.h"
20 #include "util/StreamAsString.h"
21 #include "util/MessageSystem.h"
22 #include "util/StringTo.h"
23 #include "shm/ZoneHeader.h"
25 namespace Monitor {
27 SHMReader::SHMReader() : m_header(NULL) {
28 m_shmName = Util::StreamAsString() << "/Aesalon-" << getpid();
30 m_fd = shm_open(m_shmName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
31 if(m_fd == -1) Message(Fatal, "Could not open shared memory: " << strerror(errno));
33 setupHeader();
34 setupConfiguration();
35 setupZones();
38 SHMReader::~SHMReader() {
42 uint32_t SHMReader::zoneCount() {
43 return m_header->zoneCount;
46 uint8_t *SHMReader::zoneWithData() {
47 for(uint32_t i = 0; i < m_header->zonesAllocated; i ++) {
48 if(m_zoneUseData[i % 8] & (0x01 << (i % 8))) {
49 uint8_t *zone = getZone(i);
51 if(zone == NULL) {
52 Message(Warning, "Could not open zone #" << i);
53 continue;
56 SHM::ZoneHeader *zheader = reinterpret_cast<SHM::ZoneHeader *>(zone);
58 if(sem_wait(&zheader->packetSemaphore) == -1 && errno == EAGAIN) continue;
60 return zone;
63 return NULL;
66 void SHMReader::waitForPacket() {
67 sem_wait(&m_header->packetSemaphore);
70 uint8_t *SHMReader::getZone(uint32_t id) {
71 if(id < m_zoneList.size() && m_zoneList[id] != NULL) {
72 return m_zoneList[id];
75 uint8_t *zone =
76 static_cast<uint8_t *>(mapRegion(m_header->zonePageOffset + id*m_header->zoneSize, m_header->zoneSize));
78 m_zoneList.resize(id+1);
79 m_zoneList[id] = zone;
81 return zone;
84 void *SHMReader::mapRegion(uint32_t start, uint32_t size) {
85 struct stat s;
86 if(fstat(m_fd, &s) != 0) {
87 Message(Fatal, "Could not fstat shared memory to determine size.");
90 if(s.st_size > (start+size) * AesalonPageSize) {
91 if(m_header) sem_wait(&m_header->resizeSemaphore);
93 Message(Debug, "Resizing SHM to " << start+size << " pages.");
94 if(ftruncate(m_fd, (start+size) * AesalonPageSize) != 0) {
95 Message(Fatal, "Could not resize shared memory.");
98 if(m_header) sem_post(&m_header->resizeSemaphore);
101 void *memory =
102 mmap(NULL, size * AesalonPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, start * AesalonPageSize);
104 return memory;
107 void SHMReader::unmapRegion(void *data, uint32_t size) {
108 munmap(data, size*AesalonPageSize);
111 void SHMReader::setupHeader() {
112 m_header = reinterpret_cast<SHM::Header *>(mapRegion(0, 1));
114 sem_init(&m_header->packetSemaphore, 1, 0);
115 sem_init(&m_header->resizeSemaphore, 1, 1);
118 void SHMReader::setupConfiguration() {
119 char *configurationData = static_cast<char *>(mapRegion(1, 1));
120 m_header->configDataSize = 1;
122 std::vector<Config::Vault::KeyPair> configItems;
123 Coordinator::instance()->vault()->match("*", configItems);
125 uint32_t offset = 0;
127 for(std::vector<Config::Vault::KeyPair>::iterator i = configItems.begin(); i != configItems.end(); ++i) {
128 /* Ignore all internal items. */
129 if(i->first.find("::") == 0) continue;
131 while((offset + i->first.length() + i->second.length() + 2) > m_header->configDataSize*AesalonPageSize) {
132 unmapRegion(configurationData, m_header->configDataSize);
133 m_header->configDataSize ++;
134 configurationData = static_cast<char *>(mapRegion(1, m_header->configDataSize));
136 memcpy(&configurationData[offset], i->first.c_str(), i->first.length()+1);
137 offset += i->first.length()+1;
138 memcpy(&configurationData[offset], i->second.c_str(), i->second.length()+1);
139 offset += i->second.length()+1;
143 void SHMReader::setupZones() {
144 m_header->zoneSize = Util::StringTo<uint32_t>(Coordinator::instance()->vault()->get("zoneSize"));
145 m_header->zoneUsagePages = Util::StringTo<uint32_t>(Coordinator::instance()->vault()->get("zoneUsePages"));
146 m_header->zoneCount = 0;
149 } // namespace Monitor