Line data Source code
1 : //
2 : // Author: Vladimir Migashko <migashko@gmail.com>, (C) 2012
3 : //
4 : // Copyright: See COPYING file that comes with this distribution
5 : //
6 :
7 : #ifndef VSET_VSET_BUFFER_PERSISTENT_MMAP_AD_SYNC_HPP
8 : #define VSET_VSET_BUFFER_PERSISTENT_MMAP_AD_SYNC_HPP
9 :
10 : #include <vset/buffer/tags.hpp>
11 : #include <vset/buffer/persistent/tags.hpp>
12 : #include <fas/system/nullptr.hpp>
13 :
14 : #include <errno.h>
15 : #include <unistd.h>
16 : #include <sys/mman.h>
17 :
18 : namespace vset { namespace buffer { namespace persistent{ namespace mmap{
19 :
20 9 : struct ad_sync
21 : {
22 : template<typename T>
23 24 : size_t operator()( T& t, size_t offset, size_t limit, bool sync = false) const
24 : {
25 24 : return _write(t, offset, limit, sync);
26 : }
27 :
28 : template<typename T>
29 3 : size_t operator()( T& t, bool sync = true) const
30 : {
31 3 : size_t offset = 0;
32 3 : size_t limit = t.get_aspect().template get<_size_>()(t);
33 3 : return _write(t, offset, limit, sync );
34 : }
35 :
36 : private:
37 :
38 : template<typename T>
39 27 : size_t _write( T& t, size_t offset, size_t limit, bool async) const
40 : {
41 : typedef typename T::aspect::template advice_cast<_head_type_>::type head_type;
42 27 : size_t buffer_size = t.get_aspect().template get<_buffer_size_>();
43 :
44 27 : if ( buffer_size < sizeof(head_type) )
45 0 : throw std::logic_error("buffer_size < sizeof(head_type)");
46 :
47 27 : const head_type* head = t.get_aspect().template get<_head_>()(t);
48 27 : if ( head == fas_nullptr )
49 0 : throw std::logic_error("head==nullptr");
50 :
51 27 : size_t head_offset = head->offset();
52 27 : if ( buffer_size < head->offset() )
53 0 : throw std::logic_error("buffer_size < head->offset()");
54 :
55 27 : size_t size = head->size();
56 :
57 27 : if ( offset >= size && offset!=0 )
58 0 : return 0;
59 :
60 27 : if ( offset + limit > size )
61 0 : limit = size - offset;
62 :
63 27 : size_t real_size = limit;
64 27 : size_t real_offset = offset;
65 :
66 27 : if ( offset==0 )
67 27 : real_size += head_offset;
68 : else
69 0 : real_offset += head_offset;
70 :
71 27 : if ( offset + real_size > buffer_size)
72 0 : real_size = buffer_size - offset;
73 :
74 :
75 27 : char *data = t.get_aspect().template get<_buffer_>();
76 :
77 27 : if ( -1 == ::msync( data + real_offset, real_size, async ? MS_ASYNC : MS_SYNC) )
78 0 : throw std::runtime_error(strerror(errno));
79 :
80 27 : return real_offset + real_size >= buffer_size ? 0 : offset + limit;
81 : }
82 : };
83 :
84 : }}}}
85 :
86 : #endif
|