Belle II Software development
DqmSharedMem Class Reference

Public Member Functions

 DqmSharedMem (const char *name, int size, bool writeable=true, const char *user=nullptr)
 
 DqmSharedMem (int shm_id, int sem_id)
 
 ~DqmSharedMem (void)
 
void * ptr (void)
 
int shmid (void)
 
bool IsCreated (void)
 
void lock (void)
 
void unlock (void)
 
bool isLocked (void)
 

Static Public Member Functions

static std::string getTmpFileName (std::string user, std::string name)
 
static bool getIdFromTmpFileName (std::string filename, int &shmid, int &semid)
 

Private Attributes

bool m_new {false}
 True if we created the ring buffer ourselves (and need to clean it).
 
key_t m_shmkey
 SHM key, see shmget(2).
 
key_t m_semkey
 Semaphore key.
 
int m_shmid {-1}
 shared memory id
 
int m_semid {-1}
 semaphore id
 
void * m_shmadr {nullptr}
 

Detailed Description

Definition at line 19 of file DqmSharedMem.h.

Constructor & Destructor Documentation

◆ DqmSharedMem() [1/2]

DqmSharedMem ( const char *  name,
int  size,
bool  writeable = true,
const char *  user = nullptr 
)

Definition at line 25 of file DqmSharedMem.cc.

26{
27 bool hasFile = false;
28 std::string tmpPathName;
29 // 0. Determine shared memory type
30 if (strcmp(name, "private") != 0) { // Global
31 hasFile = true;
32 if (user) {
33 tmpPathName = getTmpFileName(user, name);
34 } else {
35 tmpPathName = getTmpFileName(getenv("USER"), name);
36 }
37 printf("Open Shared Memory: %s writeable %d\n", tmpPathName.c_str(), writeable);
38 int tmpFilefd = open(tmpPathName.c_str(), O_CREAT | O_EXCL | O_RDWR, 0644);
39 // existance of file does not really imply shared mem is existing.
40 // -> better we do not rely and update the content anyway!
41 if (tmpFilefd > 0) { // a new shared memory file created
42 printf("DqmSharedMem: Creating a new tmp file %s\n", name);
43 m_new = true;
44 close(tmpFilefd); // will open again later
45 } else if (tmpFilefd == -1 && errno == EEXIST) { // shm already there
46 printf("DqmSharedMem: Updating existing tmp file %s\n", name);
47 m_new = false;
48 } else {
49 printf("DqmSharedMem: error to open tmp file %s\n", tmpPathName.c_str());
50 return;
51 }
52 m_shmkey = ftok(tmpPathName.c_str(), 1);
53 m_semkey = ftok(tmpPathName.c_str(), 2);
54 } else { // Private
55 hasFile = false;
56 m_new = true;
57 m_shmkey = IPC_PRIVATE;
58 m_semkey = IPC_PRIVATE;
59 printf("DqmSharedMem: Opening private shared memory\n");
60 }
61
62 printf("Shared memory/Semaphore Keys: $%X $%X\n", m_shmkey, m_semkey);
63 // Behavior:
64 // - IPC_CREATE will open existing or create new one
65 // - IPC_CREATE|IPC_EXCL will create new one and fail is existing
66 // - 0 will open existing one and fails if not existing
67
68 // 1. Open shared memory
69 m_shmid = shmget(m_shmkey, size * 4, IPC_CREAT | IPC_EXCL | 0644);
70 if (m_shmid >= 0) {
71 printf("Created new shm %d for key $%X\n", m_shmid, m_shmkey);
72 } else if (errno == EEXIST) {
73 m_shmid = shmget(m_shmkey, 0, 0);
74 printf("Found existing shm %d for key $%X\n", m_shmid, m_shmkey);
75 }
76 if (m_shmid < 0) {
77 perror("SharedMem::shmget");
78 return;
79 }
80 if (!writeable) {
81 printf("ShM ID %d opened Readonly\n", m_shmid);
82 m_shmadr = (int*) shmat(m_shmid, 0, SHM_RDONLY);
83 } else {
84 printf("ShM ID %d opened Writeable\n", m_shmid);
85 m_shmadr = (int*) shmat(m_shmid, 0, 0);
86 }
87 if (m_shmadr == (int*) - 1) {
88 perror("DqmSharedMem::shmat");
89 return;
90 }
91
92 // 2. Open semaphore
93
94 // Behavior:
95 // - IPC_CREATE will open existing or create new one
96 // - IPC_CREATE|IPC_EXCL will create new one and fail is existing
97 // - 0 will open existing one and fails if not existing
98 m_semid = semget(m_semkey, 1, IPC_CREAT | IPC_EXCL | 0666);
99 if (m_semid >= 0) {
100 // POSIX doesn't guarantee any particular state of our fresh semaphore
101 int semval = 1; //unlocked state
102 printf("Semaphore ID %d created for key $%X\n", m_semid, m_semkey);
103 if (semctl(m_semid, 0, SETVAL, semval) == -1) { //set 0th semaphore to semval
104 perror("Initializing semaphore with semctl() failed.");
105 return;
106 }
107 } else if (errno == EEXIST) {
108 m_semid = semget(m_semkey, 1, 0); // obtain existing one
109 printf("Found existing Semaphore ID %d for key $%X\n", m_semid, m_semkey);
110 }
111 if (m_semid < 0) {
112 perror("DqmSharedMem::shmget");
113 return;
114 }
115
116 // 3. Put id of shm and semaphore in tmp file
117 if (hasFile) {
118 // private shm dont have a file, thus need to skip
119 bool updateneeded = m_new;
120 // 3.1 check if id of shm and semaphore in tmp file need update
121 if (!m_new) {
122 int shmid = 0, semid = 0;
123 if (getIdFromTmpFileName(tmpPathName.c_str(), shmid, semid)) {
124 updateneeded = (shmid != m_shmid || semid != m_semid);
125 printf("tmp file %s content still uptodate\n", tmpPathName.c_str());
126 } else {
127 updateneeded = true; // could not open file or empty
128 }
129 }
130 // 3.2 put id of shm and semaphore in tmp file
131 if (updateneeded) {
132 char shminfo[256];
133 int tmpFilefd = open(tmpPathName.c_str(), O_RDWR, 0644);
134 if (tmpFilefd < 0) {
135 printf("SharedMem: error to reopen tmp file %s\n", tmpPathName.c_str());
136 return;
137 }
138 snprintf(shminfo, sizeof(shminfo), "%d %d\n", m_shmid, m_semid);
139 int is = write(tmpFilefd, shminfo, strlen(shminfo));
140 if (is < 0) perror("write");
141 close(tmpFilefd);
142 printf("tmp file %s has been updated with shminfo \"%s\"\n", tmpPathName.c_str(), shminfo);
143 }
144 }
145 printf("DqmSharedMem: opened. shmid = %d, semid = %d\n", m_shmid, m_semid);
146}
key_t m_shmkey
SHM key, see shmget(2).
Definition: DqmSharedMem.h:39
int m_semid
semaphore id
Definition: DqmSharedMem.h:43
int m_shmid
shared memory id
Definition: DqmSharedMem.h:42
bool m_new
True if we created the ring buffer ourselves (and need to clean it).
Definition: DqmSharedMem.h:38
key_t m_semkey
Semaphore key.
Definition: DqmSharedMem.h:40

◆ DqmSharedMem() [2/2]

DqmSharedMem ( int  shm_id,
int  sem_id 
)

Definition at line 148 of file DqmSharedMem.cc.

149{
150 // Open DqmSharedMemory with given IDs, this is only possible for read-only access
151 m_shmid = shm_id;
152 m_shmadr = (int*) shmat(m_shmid, 0, SHM_RDONLY);
153 if (m_shmadr == (int*) - 1) {
154 perror("DqmSharedMem::shmat");
155 return;
156 }
157 m_semid = sem_id;
158 printf("DqmSharedMem: open shmid = %d, semid = %d\n", m_shmid, m_semid);
159}

◆ ~DqmSharedMem()

~DqmSharedMem ( void  )

this killed the shared mems if the b2hlt... utils are run, thus commented!

Definition at line 161 of file DqmSharedMem.cc.

162{
164
165 //shmdt((const void*) m_shmadr);
166 //shmctl(m_shmid, IPC_RMID, NULL);
167 //printf("DqmSharedMem: destructor called for ID %d\n", m_shmid);
168 // TODO: problem, neither semaphore nor tmp file are deleted if they exist
169 // TODO: there is no guarantee that the destructor is called (e.g. on exit(), crash)
170 // printf("DqmSharedMem: destructor called for %s\n", m_strbuf);
171}

Member Function Documentation

◆ getIdFromTmpFileName()

bool getIdFromTmpFileName ( std::string  filename,
int &  shmid,
int &  semid 
)
static

Definition at line 193 of file DqmSharedMem.cc.

194{
195 char shminfo[256];
196 int fd = open(filename.c_str(), O_RDONLY);
197 if (fd < 0) {
198 printf("DqmSharedMem: error to reopen tmp file %s\n", filename.c_str());
199 return false;
200 }
201 shmid = -1;
202 semid = -1;
203 memset(shminfo, 0, sizeof(shminfo));
204 int n = read(fd, shminfo, sizeof(shminfo));
205 close(fd);
206 sscanf(shminfo, "%d %d", &shmid, &semid);
207 return (n >= 3 && shmid >= 0 && semid >= 0);
208}

◆ getTmpFileName()

std::string getTmpFileName ( std::string  user,
std::string  name 
)
static

Definition at line 188 of file DqmSharedMem.cc.

189{
190 return string("/tmp/") + user + string("_SHM_") + name;
191}

◆ IsCreated()

bool IsCreated ( void  )

Definition at line 183 of file DqmSharedMem.cc.

184{
185 return m_new;
186}

◆ isLocked()

bool isLocked ( void  )

Definition at line 244 of file DqmSharedMem.cc.

245{
246 int ignored = 0;
247 return (semctl(m_semid, 0, GETVAL, ignored) == 0); //0: locked, 1: unlocked
248}

◆ lock()

void lock ( void  )

Definition at line 210 of file DqmSharedMem.cc.

211{
212 struct sembuf sb;
213 sb.sem_num = 0;
214 sb.sem_op = -1;
215 sb.sem_flg = 0;
216 while (semop(m_semid, &sb, 1) == -1) {
217 if (errno == EINTR) {
218 //interrupted by signal (e.g. window size changed), try again
219 continue;
220 } else {
221 perror("lock:semop");
222 exit(-1);
223 }
224 }
225}

◆ ptr()

void * ptr ( void  )

Definition at line 173 of file DqmSharedMem.cc.

174{
175 return (void*) m_shmadr;
176}

◆ shmid()

int shmid ( void  )

Definition at line 178 of file DqmSharedMem.cc.

179{
180 return m_shmid;
181}

◆ unlock()

void unlock ( void  )

Definition at line 227 of file DqmSharedMem.cc.

228{
229 struct sembuf sb;
230 sb.sem_num = 0;
231 sb.sem_op = 1;
232 sb.sem_flg = 0;
233 while (semop(m_semid, &sb, 1) == -1) {
234 if (errno == EINTR) {
235 //interrupted by signal (e.g. window size changed), try again
236 continue;
237 } else {
238 perror("unlock:semop");
239 exit(-1);
240 }
241 }
242}

Member Data Documentation

◆ m_new

bool m_new {false}
private

True if we created the ring buffer ourselves (and need to clean it).

Definition at line 38 of file DqmSharedMem.h.

◆ m_semid

int m_semid {-1}
private

semaphore id

Definition at line 43 of file DqmSharedMem.h.

◆ m_semkey

key_t m_semkey
private

Semaphore key.

Definition at line 40 of file DqmSharedMem.h.

◆ m_shmadr

void* m_shmadr {nullptr}
private

Definition at line 44 of file DqmSharedMem.h.

◆ m_shmid

int m_shmid {-1}
private

shared memory id

Definition at line 42 of file DqmSharedMem.h.

◆ m_shmkey

key_t m_shmkey
private

SHM key, see shmget(2).

Definition at line 39 of file DqmSharedMem.h.


The documentation for this class was generated from the following files: