Menu

Defragmentation.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2009-2010 Philipp Werner <philipp.werner@st.ovgu.de>
00004  * All rights reserved.
00005  *
00006  *    Redistribution and use in source and binary forms, with or without
00007  *    modification, are permitted provided that the following conditions
00008  *    are met:
00009  *
00010  *    * Redistributions of source code must retain the above copyright
00011  *      notice, this list of conditions and the following disclaimer.
00012  *
00013  *    * Redistributions in binary form must reproduce the above copyright
00014  *      notice, this list of conditions and the following disclaimer in
00015  *      the documentation and/or other materials provided with the
00016  *      distribution.
00017  *
00018  *    * Neither the name of the copyright holders nor the names of
00019  *      contributors may be used to endorse or promote products derived
00020  *      from this software without specific prior written permission.
00021  *
00022  *
00023  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00024  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00025  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00026  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *
00036  * $Id$
00037  *
00038  ******************************************************************************/
00039 
00040 
00041 #ifndef __DEFRAGMENTATION_H_AA773DC94A45F8__
00042 #define __DEFRAGMENTATION_H_AA773DC94A45F8__
00043 
00044 
00045 #include "assert/staticerror.h"
00046 
00047 #include "debug.h"
00048 
00049 #include "mw/afp/Config.h"
00050 #include "mw/afp/DefragPolicySelector.h"
00051 #include "mw/afp/defrag/Defragmenter.h"
00052 #include "mw/afp/defrag/Headers.h"
00053 #include "mw/afp/EmptyType.h"
00054 
00055 
00056 namespace famouso {
00057     namespace mw {
00058         namespace afp {
00059 
00060 
00061             template <class AFPDC> class DefragmentationStep;
00062 
00063 
00073             template <class AFPDC>
00074             class DefragmentationProcessor {
00075 
00076                 protected:
00077 
00078                     typedef DefragPolicySelector<AFPDC> DCP;
00079 
00080                     typedef typename DCP::SizeProp::elen_t elen_t;
00081                     typedef typename DCP::SizeProp::flen_t flen_t;
00082                     typedef typename DCP::SizeProp::fcount_t fcount_t;
00083 
00084                     typedef class DCP::DemuxPolicy DemuxPolicy;
00085                     typedef class DCP::DefragStatistics Statistics;
00086 
00087 
00089                     DemuxPolicy demux;
00090 
00091                 public:
00092 
00097                     DefragmentationProcessor(flen_t mtu)
00098                             : demux(mtu) {
00099                     }
00100 
00101 
00108                     void process_fragment(DefragmentationStep<AFPDC> & ds) {
00109                         Statistics::fragment_received();
00110 
00111                         if (ds.fragment_header.error()) {
00112                             Statistics::fragment_incorrect_header();
00113                             return;
00114                         }
00115 
00116                         ds.defragmenter_handle = demux.get_defragmenter_handle(ds.fragment_header, ds.event_demux_key);
00117 
00118                         if (ds.defragmenter_handle) {
00119                             defrag::Defragmenter<DCP> * defrag = demux.get_defragmenter(ds.defragmenter_handle);
00120 
00121                             defrag->put_fragment(ds.fragment_header, ds.fragment_payload, ds.fragment_payload_length);
00122 
00123                             if (defrag->error()) {
00124                                 // Free event data if this event cannot be reconstructed for sure.
00125                                 demux.free_defragmenter(ds.defragmenter_handle);
00126                             } else {
00127                                 // Check event reconstruction status and return data if event is complete
00128                                 if (defrag->is_event_complete()) {
00129                                     ds.event_data = defrag->get_event_data();
00130                                     ds.event_length = defrag->get_event_length();
00131                                 }
00132                             }
00133                         } else {
00134                             // This fragment is outdated. The event it belongs to
00135                             // was already reconstructed (this fragment is a late duplicate
00136                             // or redundancy we do not need) or already dropped because of
00137                             // timeouts.
00138                             Statistics::fragment_outdated();
00139                         }
00140                     }
00141 
00146                     void event_processed(const DefragmentationStep<AFPDC> & ds) {
00147                         FAMOUSO_ASSERT(ds.event_complete());
00148                         if (ds.defragmenter_handle)
00149                             demux.free_defragmenter(ds.defragmenter_handle);
00150                     }
00151             };
00152 
00153 
00159             template <class AFPDC>
00160             class DefragmentationProcessorKeepEventSupport : public DefragmentationProcessor<AFPDC> {
00161 
00162                     typedef DefragPolicySelector<AFPDC> DCP;
00163 
00164                     typedef typename DCP::SizeProp::flen_t flen_t;
00165                     typedef typename DCP::SizeProp::elen_t elen_t;
00166 
00167                 public:
00168 
00170                     enum { AFP_feature_check = DCP::DemuxPolicy::support_late_delivery };
00171 
00176                     DefragmentationProcessorKeepEventSupport(flen_t mtu)
00177                             : DefragmentationProcessor<AFPDC> (mtu) {
00178                     }
00179 
00184                     void * keep_event(const DefragmentationStep<AFPDC> & ds) {
00185                         // Check whether this fragment was assigned to an complete event
00186                         if (!ds.defragmenter_handle || ds.event_data == 0)
00187                             return 0;
00188 
00189                         return DefragmentationProcessor<AFPDC>::demux.keep_defragmenter(ds.defragmenter_handle);
00190                     }
00191 
00197                     uint8_t * kept_get_event_data(void * event_handle) {
00198                         defrag::Defragmenter<DCP> * defrag = DefragmentationProcessor<AFPDC>::demux.get_kept_defragmenter(event_handle);
00199                         return defrag->get_event_data();
00200                     }
00201 
00207                     elen_t kept_get_event_length(void * event_handle) {
00208                         defrag::Defragmenter<DCP> * defrag = DefragmentationProcessor<AFPDC>::demux.get_kept_defragmenter(event_handle);
00209                         return defrag->get_event_length();
00210                     }
00211 
00216                     void kept_event_processed(void * event_handle) {
00217                         DefragmentationProcessor<AFPDC>::demux.free_kept_defragmenter(event_handle);
00218                     }
00219             };
00220 
00221 
00231             template <class AFPDC>
00232             class DefragmentationProcessorANL : private DefragmentationProcessor<AFPDC> {
00233 
00234                     typedef DefragmentationProcessor<AFPDC> Base;
00235                     typedef typename Base::flen_t flen_t;
00236 
00237                 protected:
00238 
00241                     void * last_defragmenter_handle;
00242 
00243                 public:
00244 
00249                     DefragmentationProcessorANL(flen_t mtu)
00250                             : Base(mtu), last_defragmenter_handle(0) {
00251                     }
00252 
00253 
00260                     void process_fragment(DefragmentationStep<AFPDC> & ds) {
00261                         Base::process_fragment(ds);
00262                         if (ds.event_complete())
00263                             last_defragmenter_handle = ds.defragmenter_handle;
00264                     }
00265 
00271                     void last_event_processed() {
00272                         if (last_defragmenter_handle) {
00273                             Base::demux.free_defragmenter(last_defragmenter_handle);
00274                             last_defragmenter_handle = 0;
00275                         }
00276                     }
00277             };
00278 
00282             template <>
00283             class DefragmentationProcessorANL<Disable>  {
00284 
00285                     typedef uint64_t flen_t;
00286 
00287                 public:
00288 
00293                     DefragmentationProcessorANL(flen_t mtu) {
00294                     }
00295 
00296 
00303                     void process_fragment(DefragmentationStep<Disable> & ds) {
00304                     }
00305 
00311                     void last_event_processed() {
00312                     }
00313             };
00314 
00315 
00325             template <class AFPDC>
00326             class DefragmentationStep {
00327 
00328                     typedef DefragPolicySelector<AFPDC> DCP;
00329 
00330                     typedef typename DCP::SizeProp::elen_t elen_t;
00331                     typedef typename DCP::SizeProp::flen_t flen_t;
00332                     typedef typename DCP::SizeProp::fcount_t fcount_t;
00333 
00334                     typedef typename DCP::EventDemuxKey DemuxKeyType;
00335 
00336                 protected:
00337 
00339                     defrag::Headers<DCP> fragment_header;
00340 
00342                     const uint8_t * fragment_payload;
00343 
00345                     flen_t fragment_payload_length;
00346 
00348                     DemuxKeyType event_demux_key;
00349 
00351                     void * defragmenter_handle;
00352 
00354                     uint8_t * event_data;
00355 
00357                     elen_t event_length;
00358 
00359                     friend class DefragmentationProcessor<AFPDC>;
00360                     friend class DefragmentationProcessorKeepEventSupport<AFPDC>;
00361                     friend class DefragmentationProcessorANL<AFPDC>;
00362 
00364                     template <bool cast_to_EmptyType, class ST>
00365                     struct subject_caster {
00366                         static const ST & cast(const ST & s) {
00367                             return s;
00368                         }
00369                     };
00370 
00372                     template <class ST>
00373                     struct subject_caster<true, ST> {
00374                         static EmptyType cast(const ST & s) {
00375                             return EmptyType();
00376                         }
00377                     };
00378 
00379                 public:
00380 
00388                     template <class ST>
00389                     DefragmentationStep(const uint8_t * fdata, flen_t flength, const ST & subject /* TODO: Absender-Knoten */) :
00390                             fragment_header(fdata),
00391                             fragment_payload(fdata + fragment_header.length()),
00392                             fragment_payload_length(flength - fragment_header.length()),
00393                             event_demux_key(fragment_header, subject_caster<!DemuxKeyType::uses_subject, ST>::cast(subject)),
00394                             defragmenter_handle(0),
00395                             event_data(0),
00396                             event_length(0) {
00397                     }
00398 
00404                     DefragmentationStep(const uint8_t * fdata, flen_t flength /* TODO: Absender-Knoten */) :
00405                             fragment_header(fdata),
00406                             fragment_payload(fdata + fragment_header.length()),
00407                             fragment_payload_length(flength - fragment_header.length()),
00408                             event_demux_key(fragment_header, EmptyType()),
00409                             defragmenter_handle(0),
00410                             event_data(0),
00411                             event_length(0) {
00412                         FAMOUSO_STATIC_ASSERT_ERROR(!DemuxKeyType::uses_subject,
00413                                                     wrong_constructor_for_multiple_subject_configurations, ());
00414                     }
00415 
00423                     bool error() const {
00424                         return fragment_header.error();
00425                     }
00426 
00428                     bool event_complete() const {
00429                         return event_data != 0;
00430                     }
00431 
00433                     uint8_t * get_event_data() const {
00434                         return event_data;
00435                     }
00436 
00438                     elen_t get_event_length() const {
00439                         return event_length;
00440                     }
00441             };
00442 
00443 
00447             template <>
00448             class DefragmentationStep<Disable> {
00449 
00450                     typedef uint64_t elen_t;
00451                     typedef uint64_t flen_t;
00452 
00453                 public:
00454 
00462                     template <class ST>
00463                     DefragmentationStep(const uint8_t * fdata, flen_t flength, const ST & subject /* TODO: Absender-Knoten */) {
00464                         ::logging::log::emit< ::logging::Warning>()
00465                             << PROGMEMSTRING("Dropping fragment. Defragmentation is disabled.")
00466                             << ::logging::log::endl;
00467                     }
00468 
00474                     DefragmentationStep(const uint8_t * fdata, flen_t flength /* TODO: Absender-Knoten */) {
00475                         ::logging::log::emit< ::logging::Warning>()
00476                             << PROGMEMSTRING("Dropping fragment. Defragmentation is disabled.")
00477                             << ::logging::log::endl;
00478                     }
00479 
00487                     bool error() const {
00488                         return true;
00489                     }
00490 
00492                     bool event_complete() const {
00493                         return false;
00494                     }
00495 
00497                     uint8_t * get_event_data() const {
00498                         return 0;
00499                     }
00500 
00502                     elen_t get_event_length() const {
00503                         return 0;
00504                     }
00505             };
00506 
00507 
00508         } // namespace afp
00509     } // namespace mw
00510 } // namespace famouso
00511 
00512 
00513 #endif // __DEFRAGMENTATION_H_AA773DC94A45F8__
00514