source: sources/src/dataMemoryShared.cc @ 1497:a2a9d4ede6bf

Revision 1497:a2a9d4ede6bf, 10.1 KB checked in by Dmytro Milinevskyy <millinevskyy@…>, 14 months ago (diff)

{issue #109[resolved]} reorganize misc:random helpers

Line 
1/***************************************************************************
2 *            sh.dataMemoryShared.cc
3 *
4 *  Wed Nov 21 2007
5 *  Copyright  2007  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <sys/stat.h>
35#include <string.h>
36#ifdef XSI_IPC
37#include <sys/ipc.h>
38#include <sys/shm.h>
39#endif
40#include <fcntl.h>
41#include <errno.h>
42#include <unistd.h>
43
44#include <libdodo/dataMemoryShared.h>
45#include <libdodo/toolsMisc.h>
46#include <libdodo/types.h>
47#include <libdodo/toolsCode.h>
48#include <libdodo/dataMemorySharedEx.h>
49
50namespace dodo {
51    namespace data {
52        namespace memory {
53            /**
54             * @struct __key__
55             * @brief defines shared memory key
56             */
57            struct __key__ {
58#ifdef XSI_IPC
59                int        key;             ///< key for the shared sh.data
60#else
61                dodo::string key;             ///< key for the shared sh.data
62#endif
63            };
64        };
65    };
66};
67
68using namespace dodo::data::memory;
69
70shared::__shared__::__shared__(void *data) : data(data)
71{
72}
73
74//-------------------------------------------------------------------
75
76shared::__shared__::__shared__() : data(NULL)
77{
78}
79
80//-------------------------------------------------------------------
81
82shared::shared(shared &)
83{
84}
85
86//-------------------------------------------------------------------
87
88shared::shared() : handle(-1),
89                   sh(NULL),
90                   key(new __key__),
91                   autogenerated(false)
92{
93#ifndef XSI_IPC
94    sh.size = 0;
95#endif
96}
97
98//-------------------------------------------------------------------
99
100shared::shared(int a_key) : handle(-1),
101                            sh(NULL),
102                            key(new __key__),
103                            autogenerated(false)
104{
105#ifndef XSI_IPC
106    sh.size = 0;
107#endif
108
109#ifdef XSI_IPC
110    if (a_key == 0) {
111        key->key = tools::misc::random<int>();
112
113        autogenerated = true;
114    } else {
115        key->key = a_key;
116    }
117#else
118#ifdef __FreeBSD__
119    key->key = "/tmp/";
120#else
121    key->key = "/";
122#endif
123
124    if (a_key == 0) {
125        char _key[SH_KEY_SIZE / 2 - 1];
126        tools::misc::randomBlob(_key, SH_KEY_SIZE / 2 - 1);
127
128        key->key += dodo::string(tools::code::binToHex(dodo::string(_key, SH_KEY_SIZE / 2 - 1)));
129
130        autogenerated = true;
131    } else {
132        char _key[4];
133        memcpy(_key, &a_key, 4);
134
135        key->key += dodo::string(tools::code::binToHex(dodo::string(_key, 4)));
136    }
137
138    handle = shm_open(key->key.data(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
139    if (handle == -1) {
140        delete key;
141
142        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_SHARED, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
143    }
144#endif
145}
146
147//-------------------------------------------------------------------
148
149shared::~shared()
150{
151#ifdef XSI_IPC
152    if (handle != -1 && autogenerated)
153        shmctl(handle, IPC_RMID, NULL);
154
155#else
156    if (handle != -1) {
157        if (sh.data != NULL)
158            munmap(sh.data, sh.size);
159
160        if (autogenerated)
161            shm_unlink(key->key.data());
162    }
163#endif
164
165    delete key;
166}
167
168//-------------------------------------------------------------------
169
170void
171shared::open(int a_key) const
172{
173    close();
174
175#ifdef XSI_IPC
176    if (a_key == 0) {
177        key->key = tools::misc::random<int>();
178
179        autogenerated = true;
180    } else {
181        key->key = a_key;
182    }
183#else
184#ifdef __FreeBSD__
185    key->key = "/tmp/";
186#else
187    key->key = "/";
188#endif
189
190    if (a_key == 0) {
191        char _key[SH_KEY_SIZE / 2 - 1];
192        tools::misc::randomBlob(_key, SH_KEY_SIZE / 2 - 1);
193
194        key->key += dodo::string(tools::code::binToHex(dodo::string(_key, SH_KEY_SIZE / 2 - 1)));
195
196        autogenerated = true;
197    } else {
198        char _key[4];
199        memcpy(_key, &a_key, 4);
200
201        key->key += dodo::string(tools::code::binToHex(dodo::string(_key, 4)));
202    }
203
204    handle = shm_open(key->key.data(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
205    if (handle == -1)
206        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_OPEN, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
207
208#endif
209}
210
211//-------------------------------------------------------------------
212
213void
214shared::close() const
215{
216#ifdef XSI_IPC
217    if (handle != -1 && autogenerated)
218        if (shmctl(handle, IPC_RMID, NULL) == -1)
219            dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_CLOSE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
220
221#else
222    if (handle != -1) {
223        if (sh.data != NULL)
224            if (munmap(sh.data, sh.size) == -1)
225                dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_CLOSE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
226
227        if (autogenerated)
228            if (shm_unlink(key->key.data()) == -1)
229                dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_CLOSE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
230    }
231#endif
232}
233
234//-------------------------------------------------------------------
235
236void
237shared::remove(int a_key)
238{
239#ifdef XSI_IPC
240    int handle = shmget(a_key, 0, S_IRUSR | S_IWUSR);
241    if (handle == -1)
242        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_REMOVE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
243
244    if (shmctl(handle, IPC_RMID, NULL) == -1)
245        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_REMOVE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
246
247#else
248#ifdef __FreeBSD__
249    dodo::string key = "/tmp/";
250#else
251    dodo::string key = "/";
252#endif
253
254    char _key[4];
255    memcpy(_key, &a_key, 4);
256
257    key += dodo::string(tools::code::binToHex(dodo::string(_key, 4)));
258
259    if (shm_unlink(key.data()) == -1)
260        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_REMOVE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
261
262#endif
263}
264
265//-------------------------------------------------------------------
266
267void *
268shared::map(unsigned long a_size) const
269{
270    unmap();
271
272#ifdef XSI_IPC
273    if (a_size == 0) {
274        handle = shmget(key->key, 0, S_IRUSR | S_IWUSR);
275        if (handle == -1)
276            dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_MAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
277    } else {
278        handle = shmget(key->key, a_size, IPC_CREAT | S_IRUSR | S_IWUSR);
279        if (handle == -1)
280            dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_MAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
281    }
282
283    sh.data = shmat(handle, NULL, 0);
284    if (sh.data == (void *)-1) {
285        sh.data = NULL;
286
287        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_MAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
288    }
289#else
290    if (a_size == 0) {
291        struct stat st;
292
293        if (fstat(handle, &st) == -1)
294            dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_MAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
295
296        sh.size = st.st_size;
297    } else {
298        sh.size = a_size;
299    }
300
301    if (ftruncate(handle, sh.size) != 0)
302        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_MAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
303
304    sh.data = mmap(NULL, sh.size, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);
305    if (sh.data == MAP_FAILED)
306        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_MAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
307
308#endif
309
310    return sh.data;
311}
312
313//-------------------------------------------------------------------
314
315void
316shared::unmap() const
317{
318    if (sh.data != NULL) {
319#ifdef XSI_IPC
320        if (shmdt(sh.data) == -1)
321#else
322        if (munmap(sh.data, sh.size) == -1)
323#endif
324
325            dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_UNMAP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
326
327        sh.data = NULL;
328    }
329}
330
331//-------------------------------------------------------------------
332
333void *
334shared::data() const
335{
336    return sh.data ? sh.data : map();
337}
338
339//-------------------------------------------------------------------
340
341unsigned long
342shared::size() const
343{
344#ifdef XSI_IPC
345    if (handle == -1) {
346        handle = shmget(key->key, 0, S_IRUSR | S_IWUSR);
347        if (handle == -1)
348            dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_SIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
349    }
350
351    struct shmid_ds ds;
352
353    if (shmctl(handle, IPC_STAT, &ds) == -1)
354        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_SIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
355
356    return ds.shm_segsz;
357#else
358    struct stat st;
359
360    if (fstat(handle, &st) == -1)
361        dodo_throw exception::basic(exception::MODULE_DATAMEMORYSHARED, SHAREDEX_SIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
362
363    return st.st_size;
364#endif
365}
366
367//-------------------------------------------------------------------
368
Note: See TracBrowser for help on using the repository browser.