ngc 1.4.0
 
Loading...
Searching...
No Matches
ngcbSHMDB.hpp
Go to the documentation of this file.
1
9#ifndef ngcbSHMDB_H
10#define ngcbSHMDB_H
11
12
13#ifndef __cplusplus
14#error This is a C++ include file and cannot be used from plain C
15#endif
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <sys/shm.h>
24#include <sys/sem.h>
25
29#ifndef str2str
30inline char *__str2str(char *s1, const char *s2, size_t n)
31{
32 size_t size = strlen(s2);
33 if (n > size) n = size;
34 memcpy(s1, s2, n);
35 s1[n] = '\0';
36 return (s1);
37}
38#define str2str(s1, s2, n) __str2str(s1, s2, n)
39#endif
40
44typedef union
45{
46 int val;
47 struct semid_ds *buf;
48 unsigned short *array;
50
54class ngcbSHMDB {
55public:
57 void *shmBuf;
58
60 ngcbSHMDB(const char *app, const char *s, void *initBuffer = NULL,
61 size_t size = 0) {
62
63 /*
64 * Initialize member data
65 */
66 Init_();
67
68 /*
69 * Check size and appclication name
70 */
71 if ((size == 0) && (initBuffer != NULL))
72 {
73 strcpy(ErrMsg(), "invalid database size");
74 return;
75 }
76 else if (app == NULL)
77 {
78 strcpy(ErrMsg(), "invalid application name");
79 return;
80 }
81 else if (s == NULL)
82 {
83 strcpy(ErrMsg(), "invalid key (NULL)");
84 return;
85 }
86 else if (strlen(s) == 0)
87 {
88 strcpy(ErrMsg(), "invalid key");
89 return;
90 }
91 else
92 {
93 /*
94 * We need a key-file for this instance
95 */
96 if (initBuffer != NULL)
97 {
98 /*
99 * We always create the key-file and delete it at the end
100 */
101 if (strncmp(s, "pub_", 4) == 0)
102 {
103 /*
104 * Generate a public key
105 */
106 if (strlen(s) == 4)
107 {
108 strcpy(ErrMsg(), "invalid key");
109 return;
110 }
111 else
112 {
113 snprintf(name_, sizeof(name_), "/tmp/%s_%s", app, s);
114 fd_ = open(name_, O_RDWR|O_CREAT|O_TRUNC, 0666);
115 }
116 }
117 else
118 {
119 /*
120 * Generate a private key
121 */
122 snprintf(name_, sizeof(name_), "/tmp/%s_%u_%s", app, getuid(), s);
123 fd_ = open(name_, O_RDWR|O_CREAT|O_TRUNC, 0600);
124 }
125 if (fd_ < 0)
126 {
127 name_[0] = 0;
128 sprintf(ErrMsg(), "invalid key - %s", strerror(errno));
129 return;
130 }
131 else
132 {
133 delKey_ = 1;
134 }
135 }
136 else
137 {
138 /*
139 * Check if key-file is there
140 */
141 snprintf(name_, sizeof(name_), "/tmp/%s_%u_%s", app, getuid(), s);
142 fd_ = open(name_, O_RDONLY, 0);
143 if (fd_ < 0)
144 {
145 /*
146 * Try with full qualified key
147 */
148 snprintf(name_, sizeof(name_), "/tmp/%s_%s", app, s);
149 fd_ = open(name_, O_RDONLY, 0);
150 if (fd_ < 0)
151 {
152 /*
153 * Try with public key
154 */
155 snprintf(name_, sizeof(name_), "/tmp/%s_pub_%s", app, s);
156 fd_ = open(name_, O_RDONLY, 0);
157 if (fd_ < 0)
158 {
159 /*
160 * Key-file is not there - we try to create one but then
161 * we also have to delete it at the end
162 */
163 if (strncmp(s, "pub_", 4) == 0)
164 {
165 /*
166 * Generate a public key
167 */
168 if (strlen(s) == 4)
169 {
170 strcpy(ErrMsg(), "invalid key");
171 return;
172 }
173 else
174 {
175 snprintf(name_, sizeof(name_), "/tmp/%s_%s", app, s);
176 fd_ = open(name_, O_RDWR|O_CREAT|O_TRUNC, 0666);
177 }
178 }
179 else
180 {
181 /*
182 * Generate a private key
183 */
184 snprintf(name_, sizeof(name_), "/tmp/%s_%u_%s", app, getuid(), s);
185 fd_ = open(name_, O_RDWR|O_CREAT|O_TRUNC, 0600);
186 }
187 if (fd_ < 0)
188 {
189 name_[0] = 0;
190 sprintf(ErrMsg(), "invalid key - %s", strerror(errno));
191 return;
192 }
193 else
194 {
195 delKey_ = 1;
196 }
197 }
198 }
199 }
200 }
201
202 /*
203 * Get the actual key for this instance
204 */
205 key_ = ftok(name_, 0x1f);
206 if (key_ == static_cast<key_t>(-1))
207 {
208 sprintf(ErrMsg(), "cannot get key - %s", strerror(errno));
209 close(fd_); fd_ = -1;
210 return;
211 }
212
213 if ((initBuffer == NULL) && (fd_ >= 0))
214 {
215 /*
216 * There is no need to keep the key-file open (e.g. to protect it
217 * against deletion by tmpwatch cron)
218 */
219 close(fd_); fd_ = -1;
220 }
221 }
222
223 if (initBuffer != NULL)
224 {
225 /*
226 * Create database
227 */
228 if (Create_(initBuffer, size) != 0) return;
229 server_ = 1;
230 }
231 else
232 {
233 /*
234 * Attach to database
235 */
236 if (Attach_(size) != 0) return;
237 server_ = 0;
238 }
239
240 initialized_ = 1;
241 }
242
244 virtual ~ngcbSHMDB() {
245 if (server_)
246 {
247 /*
248 * Remove database
249 */
250 Remove_();
251 }
252 else
253 {
254 /*
255 * Detach from database
256 */
257 Detach_();
258 }
259
260 /*
261 * Close key-file
262 */
263 if (fd_ >= 0) close(fd_);
264
265 /*
266 * Remove the IPC-key file
267 */
268 if (delKey_ && (strlen(name_) > 0)) remove(name_);
269 }
270
272 int Initialized() {return (initialized_);}
273
275 char *ErrMsg() {return (erms_);}
276
278 int Lock() {
279 if (sem_ >= 0)
280 {
281 if (semop(sem_, semOpLock_, 2) != 0)
282 {
283 if (errno == EINTR)
284 {
285 while (semop(sem_, semOpLock_, 2) != 0)
286 {
287 if (errno != EINTR)
288 {
289 if (errno == EIDRM) sem_ = -1; // removed (and unlocked)
290 sprintf(ErrMsg(), "cannot lock semaphore - %s", strerror(errno));
291 return (-1);
292 }
293 }
294 }
295 else
296 {
297 if (errno == EIDRM)
298 {
299 /*
300 * Semaphore has been removed (and unlocked)
301 */
302 sem_ = -1;
303 }
304 sprintf(ErrMsg(), "cannot lock semaphore - %s", strerror(errno));
305 return (-1);
306 }
307 }
308 }
309 else
310 {
311 strcpy(ErrMsg(), "invalid semaphore");
312 return (-1);
313 }
314
315 return (0);
316 }
317
319 void Unlock() {
320 if (sem_ >= 0)
321 {
322 if (semop(sem_, semOpUnlock_, 1) != 0)
323 {
324 if (errno == EIDRM) sem_ = -1; // removed (and unlocked)
325 }
326 }
327 }
328
330 int Set(const void *buffer) {
331 if (Lock() < 0)
332 {
333 return (-1);
334 }
335
336 if (shmBuf != NULL)
337 {
338 if (buffer != NULL) memcpy(shmBuf, buffer, size_);
339 else memset(shmBuf, 0, size_);
340 }
341
342 Unlock();
343
344 return (0);
345 }
346
348 int Get(void *buffer) {
349 if (buffer != NULL)
350 {
351 if (Lock() < 0)
352 {
353 return (-1);
354 }
355
356 if (shmBuf != NULL) memcpy(buffer, shmBuf, size_);
357 else memset(buffer, 0, size_);
358
359 Unlock();
360 }
361
362 return (0);
363 }
364
366 int ShmId() {return (shmId_);}
367
369 size_t Size() {return (size_);}
370
372 int SemId() {return (sem_);}
373
375 int Key() {return (key_);}
376
378 const char *KeyFile() {return (name_);}
379
381 void Remove() {Remove_();}
382
383protected:
385 void Initialized(int flag) {initialized_ = flag;}
386
387private:
389 char erms_[256];
390
392 int initialized_;
393
395 char name_[320];
396
398 key_t key_;
399
401 int delKey_;
402
404 int fd_;
405
407 int shmId_;
408
410 size_t size_;
411
413 int sem_;
414
416 int server_;
417
419 struct sembuf semOpLock_[2];
420
422 struct sembuf semOpUnlock_[1];
423
425 void Init_() {
426 initialized_ = 0;
427 name_[0] = '\0';
428 erms_[0] = '\0';
429 key_ = (key_t)-1;
430 fd_ = -1;
431 delKey_ = 0;
432 shmId_ = -1;
433 size_ = 0;
434 shmBuf = NULL;
435 sem_ = -1;
436 server_ = 0;
437
438 /*
439 * Semaphore operation:
440 * - lock semaphore
441 */
442 memset(&semOpLock_[0], 0, sizeof(struct sembuf));
443 memset(&semOpLock_[1], 0, sizeof(struct sembuf));
444 semOpLock_[1].sem_num = 0;
445 semOpLock_[1].sem_op = 1;
446 semOpLock_[1].sem_flg = SEM_UNDO;
447
448 /*
449 * Semaphore operation:
450 * - unlock semaphore
451 */
452 memset(&semOpUnlock_[0], 0, sizeof(struct sembuf));
453 semOpUnlock_[0].sem_num = 0;
454 semOpUnlock_[0].sem_op = -1;
455 semOpUnlock_[0].sem_flg = IPC_NOWAIT|SEM_UNDO;
456 }
457
459 void SemRemove_() {
460 if (sem_ >= 0)
461 {
462 ngcbSEM_CTL ctl;
463 ctl.val = 0;
464 semctl(sem_, 0, IPC_RMID, ctl); sem_ = -1;
465 }
466 }
467
469 int Create_(void *initBuffer, size_t size) {
470 ngcbSEM_CTL ctl;
471 int tmp;
472
473 /*
474 * Check size
475 */
476 if (size == 0)
477 {
478 strcpy(ErrMsg(), "invalid size");
479 return (-1);
480 }
481
482 /*
483 * Check if we have a valid key
484 */
485 if (key_ == (key_t)-1)
486 {
487 strcpy(ErrMsg(), "invalid key");
488 return (-1);
489 }
490
491 /*
492 * Ensure that the protection semaphore does not yet exist
493 */
494 tmp = semget(key_, 0, 0666);
495 if (tmp >= 0)
496 {
497 /*
498 * Remove the semaphore
499 */
500 ctl.val = 0;
501 semctl(tmp, 0, IPC_RMID, ctl);
502 }
503
504 /*
505 * Ensure that the shared memory does not yet exist
506 */
507 shmId_ = shmget(key_, 0, 0666);
508 if (shmId_ != -1)
509 {
510 /*
511 * Remove existing shared memory region
512 */
513 shmctl(shmId_, IPC_RMID, 0); shmId_ = -1;
514 }
515
516 /*
517 * Get protection semaphore
518 */
519 sem_ = semget(key_, 1, 0666|IPC_CREAT|IPC_EXCL);
520 if (sem_ == -1)
521 {
522 sprintf(ErrMsg(), "error creating semaphore - %s", strerror(errno));
523 return (-1);
524 }
525
526 /*
527 * Initialize the semaphore
528 */
529 ctl.val = 0;
530 if (semctl(sem_, 0, SETVAL, ctl) == -1)
531 {
532 sprintf(ErrMsg(), "semaphore error - %s", strerror(errno));
533
534 /*
535 * Delete the semaphore again
536 */
537 SemRemove_();
538
539 return (-1);
540 }
541
542 if (Lock() == 0)
543 {
544 /*
545 * Create a new shared memory region
546 */
547 shmId_ = shmget(key_, size, 0666|IPC_CREAT|IPC_EXCL);
548 if (shmId_ == -1)
549 {
550 sprintf(ErrMsg(), "error creating shared memory - %s",
551 strerror(errno));
552 Unlock();
553 SemRemove_();
554 return (-1);
555 }
556
557 /*
558 * Attach to the shared memory
559 */
560 shmBuf = shmat(shmId_, 0, 0);
561 if (shmBuf == (void *)-1)
562 {
563 sprintf(ErrMsg(), "cannot attach to shared memory - %s",
564 strerror(errno));
565 shmctl(shmId_, IPC_RMID, 0); shmId_ = -1;
566 shmBuf = NULL;
567 Unlock();
568 SemRemove_();
569 return (-1);
570 }
571
572 /*
573 * Initialize shared memory
574 */
575 memcpy(shmBuf, initBuffer, size);
576 Unlock();
577 }
578 else
579 {
580 SemRemove_();
581 return (-1);
582 }
583
584 size_ = size;
585
586 return (0);
587 }
588
590 int Attach_(size_t size) {
591 /*
592 * Check if we have a valid key
593 */
594 if (key_ == (key_t)-1)
595 {
596 strcpy(ErrMsg(), "invalid key");
597 return (-1);
598 }
599
600 /*
601 * Get shared memory region
602 */
603 shmId_ = shmget(key_, size, 0666);
604 if (shmId_ == -1)
605 {
606 sprintf(ErrMsg(), "cannot access shared memory - %s", strerror(errno));
607 return (-1);
608 }
609
610 if (size == 0)
611 {
612 struct shmid_ds ds;
613
614 /*
615 * Retrieve shared memory segment size
616 */
617 if (shmctl(shmId_, IPC_STAT, &ds) == -1)
618 {
619 sprintf(ErrMsg(), "cannot get shared memory size - %s",
620 strerror(errno));
621 return (-1);
622 }
623 size = ds.shm_segsz;
624 if (size == 0)
625 {
626 strcpy(ErrMsg(), "invalid shared memory segment size");
627 return (-1);
628 }
629 }
630
631 /*
632 * Attach to the shared memory
633 */
634 shmBuf = shmat(shmId_, 0, 0);
635 if (shmBuf == (void *)-1)
636 {
637 sprintf(ErrMsg(), "error attaching to shared memory - %s",
638 strerror(errno));
639 return (-1);
640 }
641
642 /*
643 * Get protection semaphore
644 */
645 sem_ = semget(key_, 1, 0666);
646 if (sem_ == -1)
647 {
648 sprintf(ErrMsg(), "cannot get semaphore - %s", strerror(errno));
649 shmdt(shmBuf); shmBuf = NULL;
650 return (-1);
651 }
652
653 size_ = size;
654 return (0);
655 }
656
658 void Remove_() {
659 /*
660 * Remove event semaphore set
661 */
662 SemRemove_();
663
664 if (shmId_ != -1)
665 {
666 if (shmBuf != NULL)
667 {
668 /*
669 * Detach from shared memory
670 */
671 shmdt(shmBuf); shmBuf = NULL;
672 }
673
674 /*
675 * Delete the shared memory
676 */
677 shmctl(shmId_, IPC_RMID, 0); shmId_ = -1;
678 }
679
680 /*
681 * Database can no longer be used
682 */
683 initialized_ = 0;
684 }
685
687 void Detach_() {
688 if (shmBuf != NULL)
689 {
690 /*
691 * Detach from shared memory
692 */
693 shmdt(shmBuf); shmBuf = NULL;
694 }
695 }
696};
697
698#endif
int Get(void *buffer)
Get shared memory buffer.
Definition ngcbSHMDB.hpp:348
int Set(const void *buffer)
Set shared memory buffer.
Definition ngcbSHMDB.hpp:330
void * shmBuf
Shared memory buffer.
Definition ngcbSHMDB.hpp:57
ngcbSHMDB(const char *app, const char *s, void *initBuffer=NULL, size_t size=0)
Constructor.
Definition ngcbSHMDB.hpp:60
int Lock()
Lock shared memory.
Definition ngcbSHMDB.hpp:278
void Unlock()
Unlock shared memory.
Definition ngcbSHMDB.hpp:319
const char * KeyFile()
Return key-file name.
Definition ngcbSHMDB.hpp:378
int Initialized()
Check if initialization was OK.
Definition ngcbSHMDB.hpp:272
void Initialized(int flag)
Set initialization flag.
Definition ngcbSHMDB.hpp:385
size_t Size()
Return shared memory size.
Definition ngcbSHMDB.hpp:369
int ShmId()
Return shared memory id.
Definition ngcbSHMDB.hpp:366
int SemId()
Return semaphore id.
Definition ngcbSHMDB.hpp:372
char * ErrMsg()
Error message.
Definition ngcbSHMDB.hpp:275
void Remove()
Remove database.
Definition ngcbSHMDB.hpp:381
int Key()
Return IPC-key.
Definition ngcbSHMDB.hpp:375
virtual ~ngcbSHMDB()
Destructor.
Definition ngcbSHMDB.hpp:244
char * __str2str(char *s1, const char *s2, size_t n)
Definition ngcbSHMDB.hpp:30
Definition ngcbSHMDB.hpp:45
struct semid_ds * buf
Definition ngcbSHMDB.hpp:47
int val
Definition ngcbSHMDB.hpp:46
unsigned short * array
Definition ngcbSHMDB.hpp:48