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