00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <utils/ipc/shm.h>
00025 #include <utils/ipc/shm_exceptions.h>
00026 #include <utils/ipc/shm_lister.h>
00027 #include <utils/ipc/semset.h>
00028
00029 #include <sys/ipc.h>
00030 #include <sys/shm.h>
00031 #include <errno.h>
00032 #include <cstring>
00033 #include <limits.h>
00034 #include <cstdlib>
00035
00036 namespace fawkes {
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 const unsigned int SharedMemory::MagicTokenSize = 16;
00214
00215
00216
00217
00218
00219 const short SharedMemory::MaxNumConcurrentReaders = 8;
00220
00221 #define WRITE_MUTEX_SEM 0
00222 #define READ_SEM 1
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 SharedMemory::SharedMemory(const char *magic_token,
00238 bool is_read_only,
00239 bool create,
00240 bool destroy_on_delete)
00241 {
00242 _magic_token = new char[MagicTokenSize];
00243 memset(_magic_token, 0, MagicTokenSize);
00244 strncpy(_magic_token, magic_token, MagicTokenSize);
00245
00246 _is_read_only = is_read_only;
00247 _destroy_on_delete = destroy_on_delete;
00248 _should_create = create;
00249
00250 _memptr = NULL;
00251 _shm_magic_token = NULL;
00252 _shm_header = NULL;
00253 _header = NULL;
00254 _data_size = 0;
00255
00256 __semset = NULL;
00257 __created = false;
00258 __shared_mem = NULL;
00259 __shared_mem_id = 0;
00260 __shared_mem_upper_bound = NULL;
00261
00262 __write_lock_aquired = false;
00263 }
00264
00265
00266
00267
00268
00269
00270 SharedMemory::SharedMemory(const SharedMemory &s)
00271 {
00272 _magic_token = new char[MagicTokenSize];
00273 memset(_magic_token, 0, MagicTokenSize);
00274 strncpy(_magic_token, s._magic_token, MagicTokenSize);
00275
00276 _is_read_only = s._is_read_only;
00277 _destroy_on_delete = s._destroy_on_delete;
00278 _should_create = s._should_create;
00279
00280 _memptr = NULL;
00281 _shm_magic_token = NULL;
00282 _shm_header = NULL;
00283 _header = s._header->clone();
00284 _data_size = 0;
00285
00286 __semset = NULL;
00287 __created = false;
00288 __shared_mem = NULL;
00289 __shared_mem_id = 0;
00290 __shared_mem_upper_bound = NULL;
00291
00292 __write_lock_aquired = false;
00293
00294 try {
00295 attach();
00296 } catch (Exception &e) {
00297 e.append("SharedMemory public copy constructor");
00298 throw;
00299 }
00300
00301 if (_memptr == NULL) {
00302 throw ShmCouldNotAttachException("Could not attach to created shared memory segment");
00303 }
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 SharedMemory::SharedMemory(const char *magic_token,
00333 SharedMemoryHeader *header,
00334 bool is_read_only, bool create, bool destroy_on_delete)
00335 {
00336 _magic_token = new char[MagicTokenSize];
00337 memset(_magic_token, 0, MagicTokenSize);
00338 strncpy(_magic_token, magic_token, MagicTokenSize);
00339
00340 _header = header;
00341 _is_read_only = is_read_only;
00342 _destroy_on_delete = destroy_on_delete;
00343 _should_create = create;
00344
00345 _memptr = NULL;
00346 _shm_magic_token = NULL;
00347 _shm_header = NULL;
00348 _data_size = 0;
00349
00350 __created = false;
00351 __semset = NULL;
00352 __shared_mem = NULL;
00353 __shared_mem_id = 0;
00354 __shared_mem_upper_bound = NULL;
00355
00356 __write_lock_aquired = false;
00357
00358 try {
00359 attach();
00360 } catch (Exception &e) {
00361 e.append("SharedMemory public constructor");
00362 throw;
00363 }
00364
00365 if (_memptr == NULL) {
00366 throw ShmCouldNotAttachException("Could not attach to created shared memory segment");
00367 }
00368 }
00369
00370
00371
00372 SharedMemory::~SharedMemory()
00373 {
00374 if ( __semset != NULL ) {
00375
00376
00377 __semset->set_destroy_on_delete( _destroy_on_delete );
00378 if ( _destroy_on_delete && ! _is_read_only ) {
00379 _shm_header->semaphore = 0;
00380 }
00381 delete __semset;
00382 }
00383 delete[] _magic_token;
00384 free();
00385 }
00386
00387
00388
00389
00390
00391
00392 void
00393 SharedMemory::free()
00394 {
00395 _memptr = NULL;
00396 _shm_header = NULL;
00397 _shm_magic_token = NULL;
00398
00399 if ((__shared_mem_id != -1) && !_is_read_only && _destroy_on_delete ) {
00400 shmctl(__shared_mem_id, IPC_RMID, NULL);
00401 __shared_mem_id = -1;
00402 }
00403 if (__shared_mem != NULL) {
00404 shmdt(__shared_mem);
00405 __shared_mem = NULL;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 void
00419 SharedMemory::attach()
00420 {
00421
00422 if (_header == NULL) {
00423
00424 throw ShmNoHeaderException();
00425 }
00426
00427 if ((_memptr != NULL) && (__shared_mem_id != -1)) {
00428
00429 return;
00430 }
00431
00432
00433 int max_id;
00434 int shm_id;
00435 struct shmid_ds shm_segment;
00436 void *shm_buf;
00437 void *shm_ptr;
00438
00439
00440 struct shmid_ds shm_info;
00441 max_id = shmctl( 0, SHM_INFO, &shm_info );
00442
00443 if (max_id >= 0) {
00444 for ( int i = 0; (_memptr == NULL) && (i <= max_id); ++i ) {
00445
00446 shm_id = shmctl( i, SHM_STAT, &shm_segment );
00447 if ( shm_id < 0 ) continue;
00448
00449
00450
00451 shm_buf = shmat(shm_id, NULL, _is_read_only ? SHM_RDONLY : 0);
00452 if (shm_buf != (void *)-1) {
00453
00454
00455 _shm_magic_token = (char *)shm_buf;
00456 _shm_header = (SharedMemory_header_t *)((char *)shm_buf + MagicTokenSize);
00457
00458 if ( strncmp(_shm_magic_token, _magic_token, MagicTokenSize) == 0 ) {
00459
00460 shm_ptr = (char *)shm_buf + MagicTokenSize
00461 + sizeof(SharedMemory_header_t);
00462
00463 if ( _header->matches( shm_ptr ) ) {
00464
00465
00466 _header->set( shm_ptr );
00467 _data_size = _header->data_size();
00468 _mem_size = sizeof(SharedMemory_header_t) + MagicTokenSize
00469 + _header->size() + _data_size;
00470
00471 if (_mem_size != (unsigned int) shm_segment.shm_segsz) {
00472 throw ShmInconsistentSegmentSizeException(_mem_size,
00473 (unsigned int) shm_segment.shm_segsz);
00474 }
00475
00476 __shared_mem_id = shm_id;
00477 __shared_mem = shm_buf;
00478 __shared_mem_upper_bound = (void *)((size_t)__shared_mem + _mem_size);
00479 _shm_upper_bound = (void *)((size_t)_shm_header->shm_addr + _mem_size);
00480 _memptr = (char *)shm_ptr + _header->size();
00481 _shm_offset = (size_t)__shared_mem - (size_t)_shm_header->shm_addr;
00482
00483 if ( _shm_header->semaphore != 0 ) {
00484
00485 add_semaphore();
00486 }
00487
00488 } else {
00489
00490 shmdt(shm_buf);
00491 }
00492 } else {
00493
00494 shmdt(shm_buf);
00495 }
00496 }
00497 }
00498 }
00499
00500 if ((_memptr == NULL) && ! _is_read_only && _should_create) {
00501
00502 __created = true;
00503 key_t key = 1;
00504
00505 _data_size = _header->data_size();
00506 _mem_size = sizeof(SharedMemory_header_t) + MagicTokenSize + _header->size() + _data_size;
00507 while ((_memptr == NULL) && (key < INT_MAX)) {
00508
00509 __shared_mem_id = shmget(key, _mem_size, IPC_CREAT | IPC_EXCL | 0666);
00510 if (__shared_mem_id != -1) {
00511 __shared_mem = shmat(__shared_mem_id, NULL, 0);
00512 if (__shared_mem != (void *)-1) {
00513 memset(__shared_mem, 0, _mem_size);
00514
00515 _shm_magic_token = (char *)__shared_mem;
00516 _shm_header = (SharedMemory_header_t *)((char *)__shared_mem + MagicTokenSize);
00517 _shm_header->shm_addr = __shared_mem;
00518
00519 _memptr = (char *)__shared_mem + MagicTokenSize
00520 + sizeof(SharedMemory_header_t)
00521 + _header->size();
00522 _shm_upper_bound = (void *)((size_t)__shared_mem + _mem_size);
00523 _shm_offset = 0;
00524 __shared_mem_upper_bound = _shm_upper_bound;
00525
00526 strncpy(_shm_magic_token, _magic_token, MagicTokenSize);
00527
00528 _header->initialize( (char *)__shared_mem + MagicTokenSize
00529 + sizeof(SharedMemory_header_t));
00530 } else {
00531
00532 shmctl(__shared_mem_id, IPC_RMID, NULL);
00533 throw ShmCouldNotAttachException("Could not create shared memory segment");
00534 }
00535 } else {
00536 if (errno == EEXIST) {
00537
00538
00539
00540 ++key;
00541 } else if (errno == EINVAL) {
00542 throw ShmCouldNotAttachException("Could not attach, segment too small or too big");
00543 } else {
00544 throw ShmCouldNotAttachException("Could not attach, shmget failed");
00545 }
00546 }
00547 }
00548 }
00549
00550 if (_memptr == NULL) {
00551 throw ShmCouldNotAttachException("Could not attach to shared memory segment");
00552 }
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 void *
00581 SharedMemory::ptr(void *addr)
00582 {
00583 if ( _shm_offset == 0 ) return addr;
00584 if ( addr == NULL) return NULL;
00585 if ( (addr < _shm_header->shm_addr) ||
00586 (addr >= _shm_upper_bound) ) {
00587 throw ShmAddrOutOfBoundsException();
00588 }
00589 return (void *)((size_t)addr + _shm_offset);
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 void *
00612 SharedMemory::addr(void *ptr)
00613 {
00614 if ( _shm_offset == 0 ) return ptr;
00615 if ( ptr == NULL) return NULL;
00616 if ( (ptr < __shared_mem) ||
00617 (ptr >= __shared_mem_upper_bound) ) {
00618 throw ShmPtrOutOfBoundsException();
00619 }
00620 return (void *)((size_t)ptr - _shm_offset);
00621 }
00622
00623
00624
00625
00626
00627 bool
00628 SharedMemory::is_read_only()
00629 {
00630 return _is_read_only;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 bool
00645 SharedMemory::is_creator()
00646 {
00647 return __created;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 void *
00657 SharedMemory::memptr()
00658 {
00659 return _memptr;
00660 }
00661
00662
00663
00664
00665
00666
00667
00668 size_t
00669 SharedMemory::data_size()
00670 {
00671 return _data_size;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680 void
00681 SharedMemory::set(void *memptr)
00682 {
00683 memcpy(_memptr, memptr, _data_size);
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 bool
00696 SharedMemory::is_destroyed()
00697 {
00698 return is_destroyed(__shared_mem_id);
00699 }
00700
00701
00702
00703
00704
00705
00706 bool
00707 SharedMemory::is_swapable()
00708 {
00709 return is_swapable(__shared_mem_id);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 bool
00721 SharedMemory::is_valid()
00722 {
00723 return (_memptr != NULL);
00724 }
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 bool
00738 SharedMemory::is_protected()
00739 {
00740 return (__semset != NULL);
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750 void
00751 SharedMemory::set_destroy_on_delete(bool destroy)
00752 {
00753 _destroy_on_delete = destroy;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 void
00765 SharedMemory::add_semaphore()
00766 {
00767 if (__semset != NULL) return;
00768 if (_memptr == NULL) throw Exception("Cannot add semaphore if not attached");
00769
00770 if ( _shm_header->semaphore != 0 ) {
00771
00772 __semset = new SemaphoreSet( _shm_header->semaphore,
00773 2,
00774 false,
00775 false );
00776 } else {
00777
00778
00779 if ( ! _is_read_only) {
00780 __semset = new SemaphoreSet( 2,
00781 true );
00782
00783 __semset->unlock(WRITE_MUTEX_SEM);
00784
00785 __semset->set_value(READ_SEM, MaxNumConcurrentReaders);
00786 _shm_header->semaphore = __semset->key();
00787 } else {
00788 throw Exception("Cannot create semaphore for read-only shmem segment");
00789 }
00790 }
00791 }
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 void
00802 SharedMemory::set_swapable(bool swapable)
00803 {
00804 if (swapable) {
00805 shmctl(__shared_mem_id, SHM_UNLOCK, NULL);
00806 } else {
00807 shmctl(__shared_mem_id, SHM_LOCK, NULL);
00808 }
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 void
00820 SharedMemory::lock_for_read()
00821 {
00822 if ( __semset == NULL ) {
00823 return;
00824 }
00825
00826 __semset->lock(READ_SEM);
00827 __lock_aquired = true;
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 bool
00849 SharedMemory::try_lock_for_read()
00850 {
00851 if ( __semset == NULL ) return false;
00852
00853 if ( __semset->try_lock(READ_SEM) ) {
00854 __lock_aquired = true;
00855 return true;
00856 } else {
00857 return false;
00858 }
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 void
00870 SharedMemory::lock_for_write()
00871 {
00872 if ( __semset == NULL ) {
00873 return;
00874 }
00875
00876 __semset->lock(WRITE_MUTEX_SEM);
00877 for ( short i = 0; i < MaxNumConcurrentReaders; ++i) {
00878 __semset->lock(READ_SEM);
00879 }
00880 __write_lock_aquired = true;
00881 __lock_aquired = true;
00882 __semset->unlock(WRITE_MUTEX_SEM);
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 bool
00904 SharedMemory::try_lock_for_write()
00905 {
00906 if ( __semset == NULL ) return false;
00907
00908 if ( __semset->try_lock(WRITE_MUTEX_SEM) ) {
00909 for ( short i = 0; i < MaxNumConcurrentReaders; ++i) {
00910 if ( ! __semset->try_lock(READ_SEM) ) {
00911
00912 for (short j = 0; j < i - 1; ++j) {
00913 __semset->unlock(READ_SEM);
00914 }
00915 __semset->unlock(WRITE_MUTEX_SEM);
00916 return false;
00917 }
00918 }
00919 __lock_aquired = true;
00920 __write_lock_aquired = true;
00921 __semset->unlock(WRITE_MUTEX_SEM);
00922 return true;
00923 } else {
00924 return false;
00925 }
00926 }
00927
00928
00929
00930
00931
00932
00933
00934
00935 void
00936 SharedMemory::unlock()
00937 {
00938 if ( __semset == NULL || ! __lock_aquired ) return;
00939
00940 if ( __write_lock_aquired ) {
00941 for ( short i = 0; i < MaxNumConcurrentReaders; ++i) {
00942 __semset->unlock(READ_SEM);
00943 }
00944 __write_lock_aquired = false;
00945 } else {
00946 __semset->unlock(READ_SEM);
00947 }
00948 }
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 bool
00962 SharedMemory::is_destroyed(int shm_id)
00963 {
00964 struct shmid_ds shm_segment;
00965
00966 if (shmctl(shm_id, IPC_STAT, &shm_segment ) == -1) {
00967 return true;
00968 } else {
00969 #ifdef __USEMISC
00970 struct ipc_perm *perm = &shm_segment.shm_perm;
00971 return (perm->mode & SHM_DEST);
00972 #else
00973 return false;
00974 #endif
00975 }
00976 }
00977
00978
00979
00980
00981
00982
00983
00984 bool
00985 SharedMemory::is_swapable(int shm_id)
00986 {
00987 #ifdef __USE_MISC
00988 struct shmid_ds shm_segment;
00989 struct ipc_perm *perm = &shm_segment.shm_perm;
00990
00991 if (shmctl(shm_id, IPC_STAT, &shm_segment ) < 0) {
00992 return true;
00993 } else {
00994 return ! (perm->mode & SHM_LOCKED);
00995 }
00996 #else
00997 return true;
00998 #endif
00999 }
01000
01001
01002
01003
01004
01005
01006 unsigned int
01007 SharedMemory::num_attached(int shm_id)
01008 {
01009 struct shmid_ds shm_segment;
01010
01011 if (shmctl(shm_id, IPC_STAT, &shm_segment ) < 0) {
01012 return 0;
01013 } else {
01014 return shm_segment.shm_nattch;
01015 }
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 void
01029 SharedMemory::list(const char *magic_token,
01030 SharedMemoryHeader *header, SharedMemoryLister *lister)
01031 {
01032
01033 lister->print_header();
01034 SharedMemoryIterator i = find(magic_token, header);
01035 SharedMemoryIterator endi = end();
01036
01037 if ( i == endi ) {
01038 lister->print_no_segments();
01039 }
01040
01041 while ( i != endi ) {
01042 lister->print_info(*i, i.shmid(), i.semaphore(), i.segmsize(),
01043 i.databuf());
01044 ++i;
01045 }
01046
01047 lister->print_footer();
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 void
01062 SharedMemory::erase(const char *magic_token,
01063 SharedMemoryHeader *header, SharedMemoryLister *lister)
01064 {
01065
01066 if (lister != NULL) lister->print_header();
01067
01068 SharedMemoryIterator i = find(magic_token, header);
01069 SharedMemoryIterator endi = end();
01070
01071 if ( (i == endi) && (lister != NULL)) {
01072 lister->print_no_segments();
01073 }
01074
01075 while ( i != endi ) {
01076 if ( i.semaphore() != 0 ) {
01077
01078 SemaphoreSet::destroy(i.semaphore());
01079 }
01080
01081
01082 shmctl(i.shmid(), IPC_RMID, NULL);
01083
01084 if ( lister != NULL) {
01085 lister->print_info(*i, i.shmid(), i.semaphore(), i.segmsize(),
01086 i.databuf());
01087 }
01088
01089 ++i;
01090 }
01091
01092 if (lister != NULL) lister->print_footer();
01093 }
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 void
01108 SharedMemory::erase_orphaned(const char *magic_token,
01109 SharedMemoryHeader *header, SharedMemoryLister *lister)
01110 {
01111
01112 if (lister != NULL) lister->print_header();
01113
01114 SharedMemoryIterator i = find(magic_token, header);
01115 SharedMemoryIterator endi = end();
01116
01117 if ( (i == endi) && (lister != NULL)) {
01118 lister->print_no_segments();
01119 }
01120
01121 unsigned int num_segments = 0;
01122
01123 while ( i != endi ) {
01124
01125 if ( i.segmnattch() == 1 ) {
01126
01127 if ( i.semaphore() != 0 ) {
01128
01129 SemaphoreSet::destroy(i.semaphore());
01130 }
01131
01132
01133 shmctl(i.shmid(), IPC_RMID, NULL);
01134
01135 if ( lister != NULL) {
01136 lister->print_info(*i, i.shmid(), i.semaphore(), i.segmsize(),
01137 i.databuf());
01138 }
01139
01140 ++num_segments;
01141 }
01142 ++i;
01143 }
01144
01145 if ( (num_segments == 0) && (lister != NULL) ) {
01146 lister->print_no_orphaned_segments();
01147 }
01148
01149 if (lister != NULL) lister->print_footer();
01150 }
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 bool
01163 SharedMemory::exists(const char *magic_token,
01164 SharedMemoryHeader *header)
01165 {
01166 return (find(magic_token, header) != end());
01167 }
01168
01169
01170
01171
01172
01173
01174
01175
01176 SharedMemory::SharedMemoryIterator
01177 SharedMemory::find(const char *magic_token, SharedMemoryHeader *header)
01178 {
01179 return SharedMemoryIterator(magic_token, header);
01180 }
01181
01182
01183
01184
01185
01186
01187 SharedMemory::SharedMemoryIterator
01188 SharedMemory::end()
01189 {
01190 return SharedMemoryIterator();
01191 }
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 SharedMemory::SharedMemoryIterator::SharedMemoryIterator()
01205 {
01206 __magic_token = NULL;
01207 __cur_shmid = -1;
01208 __cur_id = -1;
01209 __header = NULL;
01210 __shm_buf = NULL;
01211 __segmsize = 0;
01212 __segmnattch = 0;
01213
01214 struct shmid_ds shm_info;
01215 __max_id = shmctl( 0, SHM_INFO, &shm_info );
01216 }
01217
01218
01219
01220
01221
01222 SharedMemory::SharedMemoryIterator::SharedMemoryIterator(const SharedMemoryIterator &shmit)
01223 {
01224 __max_id = shmit.__max_id;
01225 __header = shmit.__header->clone();
01226 __cur_id = shmit.__cur_id;
01227 __cur_shmid = shmit.__cur_shmid;
01228 __shm_buf = NULL;
01229 __segmsize = 0;
01230 __segmnattch = 0;
01231
01232 if ( shmit.__magic_token == NULL ) {
01233 __magic_token = NULL;
01234 } else {
01235 __magic_token = strdup(shmit.__magic_token);
01236 }
01237
01238 if ( shmit.__shm_buf != (void *)-1 ) {
01239
01240 try {
01241 attach();
01242 } catch (Exception &e) {
01243
01244 }
01245 }
01246 }
01247
01248
01249
01250
01251
01252
01253 SharedMemory::SharedMemoryIterator::SharedMemoryIterator(const char *magic_token,
01254 SharedMemoryHeader *header)
01255 {
01256 __magic_token = strdup(magic_token);
01257 __header = header->clone();
01258 __cur_id = -1;
01259 __cur_shmid = -1;
01260 __shm_buf = (void *)-1;
01261 __segmsize = 0;
01262 __segmnattch = 0;
01263
01264 struct shmid_ds shm_info;
01265 __max_id = shmctl( 0, SHM_INFO, &shm_info );
01266
01267
01268 ++(*this);
01269 }
01270
01271
01272
01273 SharedMemory::SharedMemoryIterator::~SharedMemoryIterator()
01274 {
01275 delete __header;
01276 if ( __shm_buf != (void *)-1 ) {
01277 shmdt(__shm_buf);
01278 __shm_buf = (void *)-1;
01279 }
01280 if ( __magic_token ) ::free(__magic_token);
01281 }
01282
01283
01284
01285 void
01286 SharedMemory::SharedMemoryIterator::attach()
01287 {
01288 struct shmid_ds shm_segment;
01289
01290
01291 __cur_shmid = shmctl( __cur_id, SHM_STAT, &shm_segment );
01292 if ( __cur_shmid < 0 ) {
01293 throw ShmCouldNotAttachException("SharedMemoryIterator could not stat");
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 __shm_buf = shmat(__cur_shmid, NULL, SHM_RDONLY);
01305 if (__shm_buf == (void *)-1) {
01306 throw ShmCouldNotAttachException("SharedMemoryIterator could not attach");
01307 }
01308
01309
01310 __cur_shmid = shmctl( __cur_id, SHM_STAT, &shm_segment );
01311 if ( __cur_shmid < 0 ) {
01312 shmdt(__shm_buf);
01313 throw ShmCouldNotAttachException("SharedMemoryIterator could not stat (2)");
01314 }
01315
01316 __segmsize = shm_segment.shm_segsz;
01317 __segmnattch = shm_segment.shm_nattch;
01318 }
01319
01320
01321
01322 void
01323 SharedMemory::SharedMemoryIterator::reset()
01324 {
01325 if ( __header) __header->reset();
01326 if ( __shm_buf != (void *)-1) {
01327 shmdt(__shm_buf);
01328 __shm_buf = (void *)-1;
01329 }
01330 __data_buf = NULL;
01331 __semaphore = -1;
01332 __cur_shmid = -1;
01333 __segmsize = 0;
01334 __segmnattch = 0;
01335 }
01336
01337
01338
01339
01340
01341 SharedMemory::SharedMemoryIterator &
01342 SharedMemory::SharedMemoryIterator::operator++()
01343 {
01344 reset();
01345 if (__max_id >= 0) {
01346 for (++__cur_id ;__cur_id <= __max_id; ++__cur_id ) {
01347 try {
01348 attach();
01349
01350 const char *shm_magic_token = (char *)__shm_buf;
01351 SharedMemory_header_t *shm_header = (SharedMemory_header_t *)((char *)__shm_buf + MagicTokenSize);
01352
01353 if ( (strncmp(shm_magic_token, __magic_token, MagicTokenSize) == 0) &&
01354 ( !__header || __header->matches( (char *)__shm_buf + MagicTokenSize
01355 + sizeof(SharedMemory_header_t)) ) ) {
01356
01357 __semaphore = shm_header->semaphore;
01358 __data_buf = (char *)__shm_buf + MagicTokenSize
01359 + sizeof(SharedMemory_header_t)
01360 + (__header ? __header->size() : 0);
01361
01362 if ( __header ) {
01363 __header->set((char *)__shm_buf + MagicTokenSize
01364 + sizeof(SharedMemory_header_t));
01365 }
01366
01367 break;
01368 } else {
01369 reset();
01370 }
01371 } catch (ShmCouldNotAttachException &e) {
01372
01373 }
01374 }
01375 if ( __cur_id > __max_id ) {
01376
01377 reset();
01378 }
01379 }
01380
01381 return *this;
01382 }
01383
01384
01385
01386
01387
01388
01389 SharedMemory::SharedMemoryIterator
01390 SharedMemory::SharedMemoryIterator::operator++(int inc)
01391 {
01392 SharedMemoryIterator rv(*this);
01393 ++(*this);
01394 return rv;
01395 }
01396
01397
01398
01399
01400
01401
01402 SharedMemory::SharedMemoryIterator &
01403 SharedMemory::SharedMemoryIterator::operator+(unsigned int i)
01404 {
01405 for (unsigned int j = 0; j < i; ++j) {
01406 ++(*this);
01407 }
01408 return *this;
01409 }
01410
01411
01412
01413
01414
01415
01416 SharedMemory::SharedMemoryIterator &
01417 SharedMemory::SharedMemoryIterator::operator+=(unsigned int i)
01418 {
01419 for (unsigned int j = 0; j < i; ++j) {
01420 ++(*this);
01421 }
01422 return *this;
01423 }
01424
01425
01426
01427
01428
01429
01430 bool
01431 SharedMemory::SharedMemoryIterator::operator==(const SharedMemoryIterator & s) const
01432 {
01433 return (__cur_shmid == s.__cur_shmid);
01434 }
01435
01436
01437
01438
01439
01440
01441 bool
01442 SharedMemory::SharedMemoryIterator::operator!=(const SharedMemoryIterator & s) const
01443 {
01444 return ! (*this == s);
01445 }
01446
01447
01448
01449
01450
01451 const SharedMemoryHeader *
01452 SharedMemory::SharedMemoryIterator::operator*() const
01453 {
01454 return __header;
01455 }
01456
01457
01458
01459
01460
01461
01462 SharedMemory::SharedMemoryIterator &
01463 SharedMemory::SharedMemoryIterator::operator=(const SharedMemoryIterator & shmit)
01464 {
01465 if ( __shm_buf != (void *)-1 ) {
01466 shmdt(__shm_buf);
01467 __shm_buf = (void *)-1;
01468 }
01469 delete __header;
01470
01471 __max_id = shmit.__max_id;
01472 __header = shmit.__header->clone();
01473 __cur_id = shmit.__cur_id;
01474 __cur_shmid = shmit.__cur_shmid;
01475 __shm_buf = NULL;
01476
01477 if ( shmit.__magic_token == NULL ) {
01478 __magic_token = NULL;
01479 } else {
01480 __magic_token = strdup(shmit.__magic_token);
01481 }
01482
01483 if ( shmit.__shm_buf != (void *)-1 ) {
01484
01485 attach();
01486 }
01487
01488 return *this;
01489 }
01490
01491
01492
01493
01494
01495 const char *
01496 SharedMemory::SharedMemoryIterator::magic_token() const
01497 {
01498 return __magic_token;
01499 }
01500
01501
01502
01503
01504
01505 int
01506 SharedMemory::SharedMemoryIterator::shmid() const
01507 {
01508 return __cur_shmid;
01509 }
01510
01511
01512
01513
01514
01515 int
01516 SharedMemory::SharedMemoryIterator::semaphore() const
01517 {
01518 return __semaphore;
01519 }
01520
01521
01522
01523
01524
01525 size_t
01526 SharedMemory::SharedMemoryIterator::segmsize() const
01527 {
01528 return __segmsize;
01529 }
01530
01531
01532
01533
01534
01535 size_t
01536 SharedMemory::SharedMemoryIterator::segmnattch() const
01537 {
01538 return __segmnattch;
01539 }
01540
01541
01542
01543
01544
01545 void *
01546 SharedMemory::SharedMemoryIterator::databuf() const
01547 {
01548 return __data_buf;
01549 }
01550
01551 }