osaf/services/saf/amf/amfd/imm.cc        |   28 ++--
 osaf/services/saf/amf/amfd/include/imm.h |   14 +-
 osaf/services/saf/amf/amfd/include/ntf.h |    9 +-
 osaf/services/saf/amf/amfd/main.cc       |    6 +-
 osaf/services/saf/amf/amfd/ntf.cc        |  182 ++++++++++++++++++++++--------
 osaf/services/saf/amf/amfd/sgproc.cc     |    2 +-
 6 files changed, 164 insertions(+), 77 deletions(-)


Currently if AMFD gets TRY_AGAIN or TIMEOUT it logs notification and frees it.

With this patch, AMFD will give one try. AMFD will push the notification in the 
existing
job queue if hits with TRY_AGAIN or TIMEOUT in this try. Job queue already 
handles
TRY_AGAIN and TIMEOUT.

diff --git a/osaf/services/saf/amf/amfd/imm.cc 
b/osaf/services/saf/amf/amfd/imm.cc
--- a/osaf/services/saf/amf/amfd/imm.cc
+++ b/osaf/services/saf/amf/amfd/imm.cc
@@ -134,7 +134,7 @@ Job::~Job()
 }
 
 //
-AvdJobDequeueResultT ImmObjCreate::exec(SaImmOiHandleT immOiHandle)
+AvdJobDequeueResultT ImmObjCreate::exec(SaImmOiHandleT immOiHandle, 
SaNtfHandleT ntfHandle)
 {
        SaAisErrorT rc;
        AvdJobDequeueResultT res;
@@ -200,7 +200,7 @@ ImmObjCreate::~ImmObjCreate()
 }
 
 //
-AvdJobDequeueResultT ImmObjUpdate::exec(SaImmOiHandleT immOiHandle)
+AvdJobDequeueResultT ImmObjUpdate::exec(SaImmOiHandleT immOiHandle, 
SaNtfHandleT ntfHandle)
 {
        SaAisErrorT rc;
        AvdJobDequeueResultT res;
@@ -253,7 +253,7 @@ ImmObjUpdate::~ImmObjUpdate()
 }
 
 //
-AvdJobDequeueResultT ImmObjDelete::exec(SaImmOiHandleT immOiHandle)
+AvdJobDequeueResultT ImmObjDelete::exec(SaImmOiHandleT immOiHandle, 
SaNtfHandleT ntfHandle)
 {
        SaAisErrorT rc;
        AvdJobDequeueResultT res;
@@ -290,7 +290,7 @@ ImmObjDelete::~ImmObjDelete()
 }
 
 //
-AvdJobDequeueResultT ImmAdminResponse::exec(const SaImmOiHandleT handle) {
+AvdJobDequeueResultT ImmAdminResponse::exec(SaImmOiHandleT handle, 
SaNtfHandleT ntfHandle) {
        SaAisErrorT rc;
        AvdJobDequeueResultT res;
 
@@ -331,10 +331,10 @@ Job* Fifo::peek()
 {
        Job* tmp;
        
-       if (imm_job_.empty()) {
+       if (imm_ntf_job_.empty()) {
                tmp = 0;
        } else {
-               tmp = imm_job_.front();
+               tmp = imm_ntf_job_.front();
        }
        
        return tmp;
@@ -343,7 +343,7 @@ Job* Fifo::peek()
 //
 void Fifo::queue(Job* job)
 {
-       imm_job_.push(job);
+       imm_ntf_job_.push(job);
 }
 
 //
@@ -351,11 +351,11 @@ Job* Fifo::dequeue()
 {
        Job* tmp;
        
-       if (imm_job_.empty()) {
+       if (imm_ntf_job_.empty()) {
                tmp = 0;
        } else {
-               tmp = imm_job_.front();
-               imm_job_.pop();
+               tmp = imm_ntf_job_.front();
+               imm_ntf_job_.pop();
        }
        
        return tmp;
@@ -376,7 +376,7 @@ void check_and_flush_job_queue_standby_a
 }
 
 //
-AvdJobDequeueResultT Fifo::execute(SaImmOiHandleT immOiHandle)
+AvdJobDequeueResultT Fifo::execute(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle)
 {
        Job *ajob;
        AvdJobDequeueResultT ret;
@@ -395,7 +395,7 @@ AvdJobDequeueResultT Fifo::execute(SaImm
 
        TRACE_ENTER();
 
-       ret = ajob->exec(immOiHandle);
+       ret = ajob->exec(immOiHandle, ntfHandle);
        
        TRACE_LEAVE2("%d", ret);
 
@@ -418,11 +418,11 @@ void Fifo::empty()
 
 uint32_t Fifo::size()
 {
-       return imm_job_.size();
+       return imm_ntf_job_.size();
 }
 
 //
-std::queue<Job*> Fifo::imm_job_;
+std::queue<Job*> Fifo::imm_ntf_job_;
 //
 
 extern struct ImmutilWrapperProfile immutilWrapperProfile;
diff --git a/osaf/services/saf/amf/amfd/include/imm.h 
b/osaf/services/saf/amf/amfd/include/imm.h
--- a/osaf/services/saf/amf/amfd/include/imm.h
+++ b/osaf/services/saf/amf/amfd/include/imm.h
@@ -52,7 +52,7 @@ typedef enum {
 // TODO HANO Write comments
 class Job {
 public:
-       virtual AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle) = 0;
+       virtual AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle, 
SaNtfHandleT ntfHandle) = 0;
        virtual ~Job() = 0;
 };
 
@@ -63,7 +63,7 @@ public:
        std::string parentName_;
        const SaImmAttrValuesT_2 **attrValues_;
        
-       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle);
+       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle);
        
        ~ImmObjCreate();
 };
@@ -76,7 +76,7 @@ public:
        SaImmValueTypeT attrValueType_;
        void *value_;
        
-       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle);
+       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle);
        
        ~ImmObjUpdate();
 };
@@ -86,7 +86,7 @@ class ImmObjDelete : public Job {
 public:
        std::string dn;
        
-       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle);
+       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle);
        
        ~ImmObjDelete();
 };
@@ -98,7 +98,7 @@ class ImmAdminResponse : public Job {
                this->invocation_ = invocation;
                this->result_ = result;
        }
-       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle);
+       AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle);
        
        ~ImmAdminResponse() {}
  private:
@@ -116,13 +116,13 @@ public:
 
         static Job* dequeue();
     
-        static AvdJobDequeueResultT execute(SaImmOiHandleT immOiHandle);
+        static AvdJobDequeueResultT execute(SaImmOiHandleT immOiHandle, 
SaNtfHandleT ntfHandle);
 
         static void empty();
     
        static uint32_t size();
 private:
-        static std::queue<Job*> imm_job_;
+        static std::queue<Job*> imm_ntf_job_;
 };
 //
 
diff --git a/osaf/services/saf/amf/amfd/include/ntf.h 
b/osaf/services/saf/amf/amfd/include/ntf.h
--- a/osaf/services/saf/amf/amfd/include/ntf.h
+++ b/osaf/services/saf/amf/amfd/include/ntf.h
@@ -30,8 +30,8 @@
 
 #include <comp.h>
 #include <susi.h>
-
 #define AMF_NTF_SENDER "safApp=safAmfService"
+#include "imm.h"
 
 /* All states like oper, readiness etc starts from 1, so defining not 
applicable values */
 #define STATE_ID_NA  0
@@ -106,5 +106,12 @@ void avd_send_error_report_ntf(const std
 
 extern SaAisErrorT avd_ntf_init(struct cl_cb_tag*);
 extern SaAisErrorT avd_start_ntf_init_bg(void);
+class NtfSend : public Job {
+ public:
+   AvdJobDequeueResultT exec(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle);
+   SaNtfNotificationsT myntf;
+   bool already_sent;
+   ~NtfSend();
+};
 
 #endif
diff --git a/osaf/services/saf/amf/amfd/main.cc 
b/osaf/services/saf/amf/amfd/main.cc
--- a/osaf/services/saf/amf/amfd/main.cc
+++ b/osaf/services/saf/amf/amfd/main.cc
@@ -663,7 +663,7 @@ static void main_loop(void)
 
                if (pollretval == 0) {
                        // poll time out, submit some jobs (if any)
-                       polltmo = 
retval_to_polltmo(Fifo::execute(cb->immOiHandle));
+                       polltmo = 
retval_to_polltmo(Fifo::execute(cb->immOiHandle, cb->ntfHandle));
                        continue;
                }
 
@@ -686,7 +686,7 @@ static void main_loop(void)
 
                        if (evt->rcv_evt == AVD_IMM_REINITIALIZED) {
                                TRACE("Received IMM reinit msg");
-                               polltmo = 
retval_to_polltmo(Fifo::execute(cb->immOiHandle));
+                               polltmo = 
retval_to_polltmo(Fifo::execute(cb->immOiHandle, cb->ntfHandle));
                                continue;
                        }
 
@@ -748,7 +748,7 @@ static void main_loop(void)
                }
 
                // submit some jobs (if any)
-               polltmo = retval_to_polltmo(Fifo::execute(cb->immOiHandle));
+               polltmo = retval_to_polltmo(Fifo::execute(cb->immOiHandle, 
cb->ntfHandle));
        }
 
        syslog(LOG_CRIT, "AVD Thread Failed");
diff --git a/osaf/services/saf/amf/amfd/ntf.cc 
b/osaf/services/saf/amf/amfd/ntf.cc
--- a/osaf/services/saf/amf/amfd/ntf.cc
+++ b/osaf/services/saf/amf/amfd/ntf.cc
@@ -26,6 +26,7 @@
 #include <util.h>
 #include <ntf.h>
 #include "osaf_time.h"
+#include <queue>
 
 /*****************************************************************************
   Name          :  avd_send_comp_inst_failed_alarm
@@ -529,6 +530,55 @@ SaAisErrorT fill_ntf_header_part_avd(SaN
 
 }
 
+/*
+ * @brief      Tries to send notification if not sent already. If not 
successful then
+ *            does not try to Free() it. Same function will be called from job 
queue
+ *            to complete remaining task. 
+ * @param[in]  ptr to NtfSend 
+ * @return     SaAisErrorT.
+ * TODO:       Make it a member function of NtfSend() when all notification 
related handling 
+ *            is moved in separate thread.
+ */
+SaAisErrorT avd_try_send_notification(NtfSend *job) {
+  TRACE_ENTER2("Ntf Type:%x, sent status:%u", job->myntf.notificationType,
+    job->already_sent); 
+
+  SaNtfNotificationsT *myntf = &job->myntf;
+  SaAisErrorT rc = SA_AIS_OK;  
+  SaNtfNotificationHeaderT *header = nullptr;
+  SaNtfNotificationHandleT notificationHandle = 0;
+
+  if (myntf->notificationType == SA_NTF_TYPE_STATE_CHANGE) {
+    header = &myntf->notification.stateChangeNotification.notificationHeader;
+    notificationHandle = 
myntf->notification.stateChangeNotification.notificationHandle;
+  } else if (myntf->notificationType == SA_NTF_TYPE_ALARM) { 
+    header = &myntf->notification.alarmNotification.notificationHeader;
+    notificationHandle = 
myntf->notification.alarmNotification.notificationHandle;
+  }
+
+  //Try to send the notification if not sent.
+  if (job->already_sent == false) {
+    rc = saNtfNotificationSend(notificationHandle);
+    if ((rc == SA_AIS_ERR_TRY_AGAIN) || (rc == SA_AIS_ERR_TIMEOUT)) {
+      TRACE("Notification Send unsuccesful TRY_AGAIN or TIMEOUT rc:%u",rc);
+      goto done;
+    } else {
+      //To remember only Free is pending as NotificationFree() may hit with 
TRY AGAIN.
+      job->already_sent = true;
+    }
+    osaf_extended_name_free(header->notificationObject);
+    osaf_extended_name_free(header->notifyingObject);
+  }
+  
+  rc = saNtfNotificationFree(notificationHandle);
+  if ((rc == SA_AIS_ERR_TRY_AGAIN) || (rc == SA_AIS_ERR_TIMEOUT)) {
+    TRACE("Notification Free unsuccesful TRY_AGAIN or TIMEOUT rc:%u", rc);
+  }
+
+done:
+  TRACE_LEAVE();
+  return rc;
+}
 uint32_t sendAlarmNotificationAvd(AVD_CL_CB *avd_cb,
                               const std::string& ntf_object,
                               SaUint8T *add_text,
@@ -540,28 +590,29 @@ uint32_t sendAlarmNotificationAvd(AVD_CL
                               int type)
 {
        uint32_t status = NCSCC_RC_FAILURE;
-       SaNtfAlarmNotificationT myAlarmNotification;
        SaUint16T add_info_items = 0;
        SaUint64T allocation_size = 0;
+       SaAisErrorT rc = SA_AIS_OK;
 
        if (!avd_cb->active_services_exist) {
                // TODO #3051
                LOG_ER("Alarm lost for %s", ntf_object.c_str());
                return status;
        }
-
        if (avd_cb->ntfHandle == 0) {
                LOG_ER("NTF handle has not been initialized, alarm notification 
"
                                "for (%s) will be lost", ntf_object.c_str());
                return status;
        }
+       NtfSend *job = new NtfSend;
+       job->already_sent = false;
 
        if (type != 0) {
                add_info_items = 1;
                allocation_size = SA_NTF_ALLOC_SYSTEM_LIMIT;
        }
 
-       status = saNtfAlarmNotificationAllocate(avd_cb->ntfHandle, 
&myAlarmNotification,
+       status = saNtfAlarmNotificationAllocate(avd_cb->ntfHandle, 
&job->myntf.notification.alarmNotification,
                                                /* numCorrelatedNotifications */
                                                0,
                                                /* lengthAdditionalText */
@@ -582,7 +633,7 @@ uint32_t sendAlarmNotificationAvd(AVD_CL
                return NCSCC_RC_FAILURE;
        }
 
-       status = 
fill_ntf_header_part_avd(&myAlarmNotification.notificationHeader,
+       status = 
fill_ntf_header_part_avd(&job->myntf.notification.alarmNotification.notificationHeader,
                                 SA_NTF_ALARM_PROCESSING,
                                 ntf_object,
                                 add_text,
@@ -591,33 +642,33 @@ uint32_t sendAlarmNotificationAvd(AVD_CL
                                 const_cast<SaInt8T*>(AMF_NTF_SENDER),
                                 add_info,
                                 type,
-                                myAlarmNotification.notificationHandle);
+                                
job->myntf.notification.alarmNotification.notificationHandle);
        
        if (status != SA_AIS_OK) {
                LOG_ER("%s: fill_ntf_header_part_avd Failed (%u)", 
__FUNCTION__, status);
-               saNtfNotificationFree(myAlarmNotification.notificationHandle);
+               
saNtfNotificationFree(job->myntf.notification.alarmNotification.notificationHandle);
                return NCSCC_RC_FAILURE;
        }
 
-       *(myAlarmNotification.probableCause) = 
static_cast<SaNtfProbableCauseT>(probableCause);
-       *(myAlarmNotification.perceivedSeverity) = 
static_cast<SaNtfSeverityT>(perceivedSeverity);
+       *(job->myntf.notification.alarmNotification.probableCause) = 
static_cast<SaNtfProbableCauseT>(probableCause);
+       *(job->myntf.notification.alarmNotification.perceivedSeverity) = 
static_cast<SaNtfSeverityT>(perceivedSeverity);
 
-       status = saNtfNotificationSend(myAlarmNotification.notificationHandle);
+       job->myntf.notificationType = SA_NTF_TYPE_ALARM; 
 
-       
osaf_extended_name_free(myAlarmNotification.notificationHeader.notificationObject);
-       
osaf_extended_name_free(myAlarmNotification.notificationHeader.notifyingObject);
-
-       if (status != SA_AIS_OK) {
-               saNtfNotificationFree(myAlarmNotification.notificationHandle);
-               LOG_ER("%s: saNtfNotificationSend Failed (%u)", __FUNCTION__, 
status);
-               return NCSCC_RC_FAILURE;
-       }
-
-       status = saNtfNotificationFree(myAlarmNotification.notificationHandle);
-
-       if (status != SA_AIS_OK) {
-               LOG_ER("%s: saNtfNotificationFree Failed (%u)", __FUNCTION__, 
status);
-               return NCSCC_RC_FAILURE;
+       //Give atleast one try for of Send() and Free() API.
+       rc = avd_try_send_notification(job);
+        if (rc == SA_AIS_OK) {
+               //Notification Send() and Free() both successful.
+                delete job; 
+        } else if ((rc == SA_AIS_ERR_TRY_AGAIN) || (SA_AIS_ERR_TIMEOUT)) {
+               //Either Notification Send() or Free() or both un-successful.
+               //Push in the job queue.
+                TRACE("TRY-AGAIN/TIMEOUT rc:%u",rc);
+               Fifo::queue(job);
+       } else {
+               //Any other AIS return code. Not handled as of now.
+                TRACE("rc:%u",rc);
+                delete job; 
        }
 
        return status;
@@ -637,10 +688,10 @@ uint32_t sendStateChangeNotificationAvd(
                                     int additional_info_is_present)
 {
        uint32_t status = NCSCC_RC_FAILURE;
-       SaNtfStateChangeNotificationT myStateNotification;
        SaUint16T add_info_items = 0;
        SaUint64T allocation_size = 0;
        SaUint16T num_of_changedStates = 1;
+       SaAisErrorT rc = SA_AIS_OK;
 
        if (!avd_cb->active_services_exist) {
                // TODO #3051
@@ -665,9 +716,10 @@ uint32_t sendStateChangeNotificationAvd(
        if (stateId == STATE_ID_NA) {
                num_of_changedStates = 0;
        }
-
+       NtfSend *job = new NtfSend;
+       job->already_sent = false;
        status = saNtfStateChangeNotificationAllocate(avd_cb->ntfHandle,/* 
handle to Notification Service instance */
-                                                     &myStateNotification,
+                                                     
&job->myntf.notification.stateChangeNotification,
                                                      /* number of correlated 
notifications */
                                                      0,
                                                      /* length of additional 
text */
@@ -684,7 +736,7 @@ uint32_t sendStateChangeNotificationAvd(
                return NCSCC_RC_FAILURE;
        }
 
-       status = 
fill_ntf_header_part_avd(&myStateNotification.notificationHeader,
+       status = 
fill_ntf_header_part_avd(&job->myntf.notification.stateChangeNotification.notificationHeader,
                                 SA_NTF_OBJECT_STATE_CHANGE,
                                 ntf_object,
                                 add_text,
@@ -693,40 +745,39 @@ uint32_t sendStateChangeNotificationAvd(
                                 const_cast<SaInt8T*>(AMF_NTF_SENDER),
                                 add_info,
                                 additional_info_is_present,
-                                myStateNotification.notificationHandle);
+                                
job->myntf.notification.stateChangeNotification.notificationHandle);
        
        if (status != SA_AIS_OK) {
                LOG_ER("%s: fill_ntf_header_part_avd Failed (%u)", 
__FUNCTION__, status);
-               saNtfNotificationFree(myStateNotification.notificationHandle);
+               
saNtfNotificationFree(job->myntf.notification.stateChangeNotification.notificationHandle);
                return NCSCC_RC_FAILURE;
        }
 
-       *(myStateNotification.sourceIndicator) = 
static_cast<SaNtfSourceIndicatorT>(sourceIndicator);
+       *(job->myntf.notification.stateChangeNotification.sourceIndicator) = 
static_cast<SaNtfSourceIndicatorT>(sourceIndicator);
        
        if (num_of_changedStates == 1) {
-               myStateNotification.changedStates->stateId = stateId;
-               myStateNotification.changedStates->oldStatePresent = SA_TRUE;
-               myStateNotification.changedStates->oldState = oldstate;
-               myStateNotification.changedStates->newState = newState;
+               
job->myntf.notification.stateChangeNotification.changedStates->stateId = 
stateId;
+               
job->myntf.notification.stateChangeNotification.changedStates->oldStatePresent 
= SA_TRUE;
+               
job->myntf.notification.stateChangeNotification.changedStates->oldState = 
oldstate;
+               
job->myntf.notification.stateChangeNotification.changedStates->newState = 
newState;
        }
+       job->myntf.notificationType = SA_NTF_TYPE_STATE_CHANGE; 
 
-       status = saNtfNotificationSend(myStateNotification.notificationHandle);
-
-       
osaf_extended_name_free(myStateNotification.notificationHeader.notificationObject);
-       
osaf_extended_name_free(myStateNotification.notificationHeader.notifyingObject);
-
-       if (status != SA_AIS_OK) {
-               saNtfNotificationFree(myStateNotification.notificationHandle);
-               LOG_ER("%s: saNtfNotificationSend Failed (%u)", __FUNCTION__, 
status);
-               return NCSCC_RC_FAILURE;
-       }
-
-       status = saNtfNotificationFree(myStateNotification.notificationHandle);
-
-       if (status != SA_AIS_OK) {
-               LOG_ER("%s: saNtfNotificationFree Failed (%u)", __FUNCTION__, 
status);
-               return NCSCC_RC_FAILURE;
-       }
+       //Give atleast one try for of Send() and Free() API.
+        rc = avd_try_send_notification(job);
+        if (rc == SA_AIS_OK) {
+                //Notification Send() and Free() both successful.
+                delete job;
+        } else if ((rc == SA_AIS_ERR_TRY_AGAIN) || (SA_AIS_ERR_TIMEOUT)) {
+                //Either Notification Send() or Free() or both un-successful.
+                //Push in the job queue.
+                TRACE("TRY-AGAIN/TIMEOUT rc:%u",rc);
+                Fifo::queue(job);
+        } else {
+                //Any other AIS return code. Not handled as of now.
+                TRACE("rc:%u",rc);
+                delete job;
+        }
 
        return status;
 
@@ -838,3 +889,32 @@ SaAisErrorT avd_start_ntf_init_bg(void)
 
        return SA_AIS_OK;
 }
+
+AvdJobDequeueResultT NtfSend::exec(SaImmOiHandleT immOiHandle, SaNtfHandleT 
ntfHandle) {
+  AvdJobDequeueResultT res;
+  SaAisErrorT rc = SA_AIS_OK;
+  TRACE_ENTER2("Ntf Type:%x, sent status:%u", myntf.notificationType,
+    already_sent); 
+
+  rc = avd_try_send_notification(this);
+  if (rc == SA_AIS_OK) {
+    delete Fifo::dequeue();
+    res = JOB_EXECUTED;
+  } else if (rc == SA_AIS_ERR_TRY_AGAIN) {
+    TRACE("TRY-AGAIN");
+    res = JOB_ETRYAGAIN;
+  } else if (rc == SA_AIS_ERR_TIMEOUT) {
+    TRACE("TIMEOUT");
+    res = JOB_ETRYAGAIN;
+  } else {
+    delete Fifo::dequeue();
+    LOG_ER("%s: Notification Send FAILED %u", __FUNCTION__, rc);
+    res = JOB_ERR;
+  }
+
+  TRACE_LEAVE();
+  return res;
+}
+
+NtfSend::~NtfSend() {
+}
diff --git a/osaf/services/saf/amf/amfd/sgproc.cc 
b/osaf/services/saf/amf/amfd/sgproc.cc
--- a/osaf/services/saf/amf/amfd/sgproc.cc
+++ b/osaf/services/saf/amf/amfd/sgproc.cc
@@ -801,7 +801,7 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb
                                                */
                                                AvdJobDequeueResultT job_res = 
JOB_EXECUTED;
                                                while (job_res == JOB_EXECUTED)
-                                                       job_res = 
Fifo::execute(cb->immOiHandle);
+                                                       job_res = 
Fifo::execute(cb->immOiHandle, cb->ntfHandle);
 
                                                goto done;
                                        } else {

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to