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