servlib/prophet/AckList.cc
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2007 Baylor University
       
     3  *
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  *
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  *
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 #include <time.h>
       
    18 #include "BundleCore.h"
       
    19 #include "AckList.h"
       
    20 
       
    21 namespace prophet
       
    22 {
       
    23 
       
    24 AckList::~AckList()
       
    25 {
       
    26     for (palist::iterator i = acks_.begin(); i != acks_.end(); i++)
       
    27     {
       
    28         delete (*i);
       
    29     }
       
    30     acks_.clear();
       
    31 }
       
    32 
       
    33 bool
       
    34 AckList::insert(const std::string& dest_id, u_int32_t cts,
       
    35                 u_int32_t seq, u_int32_t ets)
       
    36 {
       
    37     // default to 1 day
       
    38     if (ets == 0) ets = 86400;
       
    39 
       
    40     Ack a(dest_id,cts,seq,ets); 
       
    41     return insert(&a);
       
    42 }
       
    43 
       
    44 bool
       
    45 AckList::insert(const Bundle* b, const BundleCore* core)
       
    46 {
       
    47     if (b == NULL || core == NULL) return false;
       
    48 
       
    49     return insert(core->get_route(b->destination_id()),
       
    50                   b->creation_ts(),
       
    51                   b->sequence_num(),
       
    52                   b->expiration_ts());
       
    53 }
       
    54 
       
    55 bool
       
    56 AckList::insert(const Ack* a)
       
    57 {
       
    58     if (a == NULL) return false;
       
    59 
       
    60     Ack* na = new Ack(*a);
       
    61 
       
    62     // attempt to insert
       
    63     if (acks_.insert(na).second)
       
    64         return true;
       
    65 
       
    66     // failed, so free up memory
       
    67     delete na;
       
    68     return false;
       
    69 }
       
    70 
       
    71 size_t
       
    72 AckList::clone(PointerList<Ack>& list) const
       
    73 {
       
    74     size_t num = 0;
       
    75     // clear the incoming
       
    76     list.clear();
       
    77     // walk the internal, visiting each Ack
       
    78     for (palist::const_iterator i = acks_.begin(); i != acks_.end(); i++)
       
    79     {
       
    80         // give away a copy of each visited Ack
       
    81         list.push_back(new Ack(**i));
       
    82         // ... counting as we go
       
    83         num++;
       
    84     }
       
    85     // inform caller of how many elements
       
    86     return num;
       
    87 }
       
    88 
       
    89 size_t
       
    90 AckList::fetch(const std::string& dest_id, PointerList<Ack>* list) const
       
    91 {
       
    92     size_t num = 0;
       
    93 
       
    94     // clear incoming, if set
       
    95     if (list != NULL) list->clear();
       
    96 
       
    97     // create a search parameter of palist::key_type
       
    98     Ack a(dest_id);
       
    99 
       
   100     // find the beginning of the sequence that matches dest_id
       
   101     palist::const_iterator i = acks_.lower_bound(&a);
       
   102 
       
   103     // walk along until either the string no longer matches or
       
   104     // we fall off the end of the sequence
       
   105     while (i != acks_.end() && (*i)->dest_id().compare(dest_id) == 0)
       
   106     {
       
   107         // if set, give the list pointer a copy of each Ack we find
       
   108         if (list != NULL) list->push_back(new Ack(**(i++)));
       
   109         num++;
       
   110     }
       
   111 
       
   112     // inform the caller of how many were found
       
   113     return num;
       
   114 }
       
   115 
       
   116 size_t
       
   117 AckList::expire()
       
   118 {
       
   119     size_t num = 0;
       
   120 
       
   121     // grab current epoch seconds
       
   122     time_t now = time(0);
       
   123 
       
   124     // walk the list of Acks, careful how we increment since
       
   125     // the erase() operation screws up iterator state
       
   126     for (palist::iterator i = acks_.begin(); i != acks_.end(); )
       
   127     {
       
   128         Ack* a = *i;
       
   129         // test for expired condition
       
   130         if (now - a->cts() > a->ets())
       
   131         {
       
   132             num++;
       
   133             // post increment to sidestep iterator screwiness
       
   134             acks_.erase(i++);
       
   135             // clear up memory 
       
   136             delete a;
       
   137         }
       
   138         // not expired, increment past this one
       
   139         else i++;
       
   140     }
       
   141     // inform caller of how many were removed
       
   142     return num;
       
   143 }
       
   144 
       
   145 bool
       
   146 AckList::is_ackd(const std::string& dest_id,
       
   147                  u_int32_t cts, u_int32_t seq) const
       
   148 {
       
   149     // create search parameter of type palist::key_type
       
   150     Ack a(dest_id);
       
   151 
       
   152     // initialize iterator to beginning of matching sequence
       
   153     palist::iterator i = acks_.lower_bound(&a);
       
   154 
       
   155     // walk the sequence until no more matches, or end of sequence
       
   156     while (i != acks_.end())
       
   157     {
       
   158         // test for no-more-matches
       
   159         if ((*i)->dest_id().compare(dest_id) != 0)
       
   160             break;
       
   161         // all parameters match?
       
   162         if ((*i)->cts() == cts && (*i)->seq() == seq)
       
   163             return true;
       
   164         i++;
       
   165     }
       
   166     // not found, therefore must not be Ack'd
       
   167     return false;
       
   168 }
       
   169 
       
   170 }; // namespace prophet