Menu

AFPPublisherEventChannel.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2009-2010 Philipp Werner <philipp.werner@st.ovgu.de>
00004  *                         Michael Schulze <mschulze@ivs.cs.uni-magdeburg.de>
00005  * All rights reserved.
00006  *
00007  *    Redistribution and use in source and binary forms, with or without
00008  *    modification, are permitted provided that the following conditions
00009  *    are met:
00010  *
00011  *    * Redistributions of source code must retain the above copyright
00012  *      notice, this list of conditions and the following disclaimer.
00013  *
00014  *    * Redistributions in binary form must reproduce the above copyright
00015  *      notice, this list of conditions and the following disclaimer in
00016  *      the documentation and/or other materials provided with the
00017  *      distribution.
00018  *
00019  *    * Neither the name of the copyright holders nor the names of
00020  *      contributors may be used to endorse or promote products derived
00021  *      from this software without specific prior written permission.
00022  *
00023  *
00024  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00025  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  *
00037  * $Id$
00038  *
00039  ******************************************************************************/
00040 
00041 #ifndef __AFPPUBLISHEREVENTCHANNEL_H_472698B5E7680A__
00042 #define __AFPPUBLISHEREVENTCHANNEL_H_472698B5E7680A__
00043 
00044 
00045 #include "mw/afp/Fragmenter.h"
00046 #include "mw/afp/CommonPolicySelector.h"
00047 
00048 #include "debug.h"
00049 #include "mw/common/Event.h"
00050 
00051 #include "assert/staticerror.h"
00052 
00053 
00054 namespace famouso {
00055     namespace mw {
00056         namespace afp {
00057 
00058 
00059             using famouso::mw::Event;
00060             using famouso::mw::Subject;
00061 
00062 
00070             template < class PEC, class AFPFC, uint32_t mtu, class EventType = Event >
00071             class AFPPublisherEventChannel : public PEC  {
00072 
00074                     typedef CommonPolicySelector<AFPFC> FCP;
00075 
00077                     FAMOUSO_STATIC_ASSERT_ERROR(mtu == (typename FCP::SizeProp::flen_t)mtu,
00078                                                 MTU_too_large_for_used_SizeProperties, ());
00079 
00081                     enum { _mtu = mtu };
00082 
00084                     uint8_t _buffer[_mtu];
00085 
00086                 public:
00087 
00092                     AFPPublisherEventChannel(const Subject & s) :
00093                             PEC(s) {
00094                     }
00095 
00101                     bool publish(const EventType & e) {
00102                         Event fragment_e(e.subject);
00103                         fragment_e.data = _buffer;
00104 
00105                         if (e.length != (typename FCP::SizeProp::elen_t) e.length) {
00106                             ::logging::log::emit< ::logging::Error>()
00107                                 << PROGMEMSTRING("AFP: Cannot publish event... too large.")
00108                                 << ::logging::log::endl;
00109                             return false;
00110                         }
00111 
00112                         afp::Fragmenter<AFPFC, _mtu> f(e.data, e.length);
00113 
00114                         if (f.error())
00115                             return false;
00116 
00117                         while ( (fragment_e.length = f.get_fragment(fragment_e.data)) ) {
00118                             PEC::publish(fragment_e);
00119                         }
00120 
00121                         return !f.error();
00122                     }
00123             };
00124 
00125 
00132             template <class PEC, class AFPFC, class EventType>
00133             class AFPPublisherEventChannel<PEC, AFPFC, 0, EventType> : public PEC  {
00134 
00136                     typedef CommonPolicySelector<AFPFC> FCP;
00137 
00139                     typedef typename FCP::Allocator Allocator;
00140 
00142                     uint32_t _mtu;
00143 
00145                     uint8_t * _buffer;
00146 
00147                 public:
00148 
00154                     AFPPublisherEventChannel(const Subject &s, uint16_t mtu)
00155                             : PEC(s), _mtu(mtu) {
00156                         _buffer = Allocator::alloc(mtu);
00157                         if (!_buffer) {
00158                             ::logging::log::emit< ::logging::Error>()
00159                                 << PROGMEMSTRING("AFP: Out of memory")
00160                                 << ::logging::log::endl;
00161                         }
00162                     }
00163 
00167                     ~AFPPublisherEventChannel() {
00168                         if (_buffer)
00169                             Allocator::free(_buffer);
00170                     }
00171 
00177                     bool publish(const EventType & e) {
00178                         if (!_buffer)
00179                             return false;
00180 
00181                         Event fragment_e(e.subject);
00182                         fragment_e.data = _buffer;
00183 
00184                         if (e.length != (typename FCP::SizeProp::elen_t) e.length) {
00185                             ::logging::log::emit< ::logging::Error>()
00186                                 << PROGMEMSTRING("AFP: Cannot publish event... too large.")
00187                                 << ::logging::log::endl;
00188                             return false;
00189                         }
00190 
00191                         afp::Fragmenter<AFPFC> f(e.data, e.length, _mtu);
00192 
00193                         if (f.error())
00194                             return false;
00195 
00196                         while ( (fragment_e.length = f.get_fragment(fragment_e.data)) ) {
00197                             PEC::publish(fragment_e);
00198                         }
00199 
00200                         return !f.error();
00201                     }
00202             };
00203 
00204         } // namespace afp
00205     } // namespace mw
00206 } // namespace famouso
00207 
00208 
00209 #endif // __AFPPUBLISHEREVENTCHANNEL_H_472698B5E7680A__
00210