servlib/reg/Registration.cc
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/reg/Registration.cc	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,228 @@
+/*
+ *    Copyright 2004-2006 Intel Corporation
+ * 
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <dtn-config.h>
+#endif
+
+#include "Registration.h"
+#include "bundling/Bundle.h"
+#include "bundling/BundleDaemon.h"
+#include "bundling/BundleList.h"
+#include "session/Session.h"
+#include "storage/GlobalStore.h"
+
+namespace dtn {
+
+//----------------------------------------------------------------------
+const char*
+Registration::failure_action_toa(failure_action_t action)
+{
+    switch(action) {
+    case DROP:  return "DROP";
+    case DEFER:	return "DEFER";
+    case EXEC:  return "EXEC";
+    }
+
+    return "__INVALID__";
+}
+
+//----------------------------------------------------------------------
+Registration::Registration(u_int32_t regid,
+                           const EndpointIDPattern& endpoint,
+                           u_int32_t failure_action,
+                           u_int32_t session_flags,
+                           u_int32_t expiration,
+                           const std::string& script)
+    
+    : Logger("Registration", "/dtn/registration/%d", regid),
+      regid_(regid),
+      endpoint_(endpoint),
+      failure_action_(failure_action),
+      session_flags_(session_flags),
+      script_(script),
+      expiration_(expiration),
+      expiration_timer_(NULL),
+      active_(false),
+      expired_(false),
+      delivery_cache_(std::string(logpath()) + "/delivery_cache", 1024)
+{
+    struct timeval now;
+    ::gettimeofday(&now, 0);
+    creation_time_ = now.tv_sec;
+    
+    init_expiration_timer();
+}
+
+//----------------------------------------------------------------------
+Registration::Registration(const oasys::Builder&)
+    : Logger("Registration", "/dtn/registration"),
+      regid_(0),
+      endpoint_(),
+      failure_action_(DEFER),
+      script_(),
+      expiration_(0),
+      creation_time_(0),
+      expiration_timer_(NULL),
+      active_(false),
+      expired_(false),
+      delivery_cache_(std::string(logpath()) + "/delivery_cache", 1024)
+{
+}
+
+//----------------------------------------------------------------------
+Registration::~Registration()
+{
+    cleanup_expiration_timer();
+}
+
+//----------------------------------------------------------------------
+bool
+Registration::deliver_if_not_duplicate(Bundle* bundle)
+{
+    if (! delivery_cache_.add_entry(bundle, EndpointID::NULL_EID())) {
+        log_debug("suppressing duplicate delivery of bundle *%p", bundle);
+        return false;
+    }
+    
+    log_debug("delivering bundle *%p", bundle);
+    deliver_bundle(bundle);
+    return true;
+}
+
+//----------------------------------------------------------------------
+void
+Registration::session_notify(Bundle* bundle)
+{
+    (void)bundle;
+    PANIC("generic session_notify implementation should never be called");
+}
+
+//----------------------------------------------------------------------
+void
+Registration::force_expire()
+{
+    ASSERT(active_);
+    
+    cleanup_expiration_timer();
+    set_expired(true);
+}
+
+//----------------------------------------------------------------------
+void
+Registration::cleanup_expiration_timer()
+{
+    if (expiration_timer_) {
+        // try to cancel the expiration timer. if it is still pending,
+        // then the timer will clean itself up when it eventually
+        // fires. otherwise, assert that we have actually expired and
+        // delete the timer itself.
+        bool pending = expiration_timer_->cancel();
+        
+        if (! pending) {
+            ASSERT(expired_);
+            delete expiration_timer_;
+        }
+        
+        expiration_timer_ = NULL;
+    }
+}
+
+//----------------------------------------------------------------------
+void
+Registration::serialize(oasys::SerializeAction* a)
+{
+    a->process("endpoint", &endpoint_);
+    a->process("regid", &regid_);
+    a->process("failure_action", &failure_action_);
+    a->process("session_flags", &session_flags_);
+    a->process("script", &script_);
+    a->process("creation_time", &creation_time_);
+    a->process("expiration", &expiration_);
+
+    // finish constructing the object after unserialization
+    if (a->action_code() == oasys::Serialize::UNMARSHAL) {
+        init_expiration_timer();
+    }
+
+    logpathf("/dtn/registration/%d", regid_);
+}
+
+//----------------------------------------------------------------------
+int
+Registration::format(char* buf, size_t sz) const
+{
+    return snprintf(buf, sz,
+                    "id %u: %s %s (%s%s) [expiration %d%s%s%s%s]",
+                    regid(),
+                    active() ? "active" : "passive",
+                    endpoint().c_str(),
+                    failure_action_toa(failure_action()),
+                    failure_action() == Registration::EXEC ?
+                      script().c_str() : "",
+                    expiration(),
+                    session_flags() != 0 ? " session:" : "",
+                    (session_flags() & Session::CUSTODY) ? " custody" : "",
+                    (session_flags() & Session::PUBLISH) ? " publish" : "",
+                    (session_flags() & Session::SUBSCRIBE) ? " subscribe" : ""
+        );
+}
+
+//----------------------------------------------------------------------
+void
+Registration::init_expiration_timer()
+{
+    if (expiration_ != 0) {
+        struct timeval when, now;
+        when.tv_sec  = creation_time_ + expiration_;
+        when.tv_usec = 0;
+
+        ::gettimeofday(&now, 0);
+
+        long int in_how_long = TIMEVAL_DIFF_MSEC(when, now);
+        if (in_how_long < 0) {
+            log_warn("scheduling IMMEDIATE expiration for registration id %d: "
+                     "[creation_time %u, expiration %u, now %u]", 
+                     regid_, creation_time_, expiration_, (u_int)now.tv_sec);
+        } else {
+            log_debug("scheduling expiration for registration id %d at %u.%u "
+                      "(in %ld seconds): ", regid_,
+                      (u_int)when.tv_sec, (u_int)when.tv_usec,
+                      in_how_long / 1000);
+        }
+        
+        expiration_timer_ = new ExpirationTimer(this);
+        expiration_timer_->schedule_at(&when);
+
+    } else {
+        set_expired(true);
+    }
+}
+
+//----------------------------------------------------------------------
+void
+Registration::ExpirationTimer::timeout(const struct timeval& now)
+{
+    (void)now;
+    
+    reg_->set_expired(true);
+                      
+    if (! reg_->active()) {
+        BundleDaemon::post(new RegistrationExpiredEvent(reg_));
+    } 
+}
+
+} // namespace dtn