"Fossies" - the Fresh Open Source Software Archive

Member "opensaf-5.21.09/src/imm/agent/imma_init.cc" (14 Sep 2021, 18000 Bytes) of package /linux/misc/opensaf-5.21.09.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "imma_init.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.21.06_vs_5.21.09.

    1 /*      -*- OpenSAF  -*-
    2  *
    3  * (C) Copyright 2008 The OpenSAF Foundation
    4  * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
    5  *
    6  * This program is distributed in the hope that it will be useful, but
    7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    8  * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
    9  * under the GNU Lesser General Public License Version 2.1, February 1999.
   10  * The complete license can be accessed from the following location:
   11  * http://opensource.org/licenses/lgpl-license.php
   12  * See the Copying file included with the OpenSAF distribution for full
   13  * licensing terms.
   14  *
   15  * Author(s): Ericsson AB
   16  *
   17  */
   18 
   19 /*****************************************************************************
   20 
   21   DESCRIPTION:
   22 
   23   This file contains the IMMSv's service part IMMA's Init/Destory routines.
   24 
   25 ******************************************************************************/
   26 
   27 #include <string.h>
   28 
   29 #include "imma.h"
   30 #include "base/osaf_poll.h"
   31 #include "base/osaf_extended_name.h"
   32 #include <saAis.h>
   33 #include "mds/mds_dl_api.h"
   34 
   35 /*****************************************************************************
   36  global data used by IMMA
   37  *****************************************************************************/
   38 
   39 /* IMMA Agent creation specific LOCK */
   40 static pthread_mutex_t imma_agent_lock = PTHREAD_MUTEX_INITIALIZER;
   41 
   42 /* Protected by imma_agent_lock */
   43 static uint32_t imma_use_count = 0;
   44 
   45 IMMA_CB imma_cb;
   46 
   47 /********************************************************************
   48  Name    :  imma_sync_with_immnd
   49 
   50  Description : This is for IMMA to sync with IMMND when it gets MDS callback
   51 
   52    This is needed to avoid a potential endless loop of TRY_AGAIN when
   53    the first client connects. The first client initializes the IMMA
   54    library. If IMMND is not up when the first need to send to IMMND
   55    arises, IMMA will reply with TRY_AGAIN, but IMMA will also
   56    shut down the library (since the initialize failed and this was
   57    the first/last client.
   58    Repeat.
   59    Code cloned from CkpSv.
   60 **********************************************************************/
   61 
   62 static uint32_t imma_sync_with_immnd(IMMA_CB *cb) {
   63   TRACE_ENTER();
   64 
   65   m_NCS_LOCK(&cb->immnd_sync_lock, NCS_LOCK_WRITE);
   66 
   67   if (cb->is_immnd_up) {
   68     m_NCS_UNLOCK(&cb->immnd_sync_lock, NCS_LOCK_WRITE);
   69     return NCSCC_RC_SUCCESS;
   70   }
   71   TRACE("Blocking first client");
   72   cb->immnd_sync_awaited = true;
   73   if (m_NCS_SEL_OBJ_CREATE(&cb->immnd_sync_sel) != NCSCC_RC_SUCCESS) {
   74     m_NCS_UNLOCK(&cb->immnd_sync_lock, NCS_LOCK_WRITE);
   75     return NCSCC_RC_FAILURE;
   76   }
   77   m_NCS_UNLOCK(&cb->immnd_sync_lock, NCS_LOCK_WRITE);
   78 
   79   /* Await indication from MDS saying IMMND is up */
   80   osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(cb->immnd_sync_sel), 30000);
   81   TRACE("Blocking wait released");
   82 
   83   /* Destroy the sync - object */
   84   m_NCS_LOCK(&cb->immnd_sync_lock, NCS_LOCK_WRITE);
   85 
   86   cb->immnd_sync_awaited = false;
   87   m_NCS_SEL_OBJ_DESTROY(&cb->immnd_sync_sel);
   88 
   89   m_NCS_UNLOCK(&cb->immnd_sync_lock, NCS_LOCK_WRITE);
   90 
   91   TRACE_LEAVE();
   92   return NCSCC_RC_SUCCESS;
   93 }
   94 
   95 /****************************************************************************
   96   Name          : imma_create
   97 
   98   Description   : This routine creates & initializes the IMMA control block.
   99 
  100   Arguments     : create_info - ptr to the create info
  101                   sv_id - service id, either NCSMDS_SVC_ID_IMMA_OM or
  102                           NCSMDS_SVC_ID_IMMA_OI.
  103 
  104   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
  105 
  106   Notes         : None
  107 ******************************************************************************/
  108 static uint32_t imma_create(NCSMDS_SVC_ID sv_id) {
  109   IMMA_CB *cb = &imma_cb;
  110   uint32_t rc;
  111 
  112   char *value;
  113 
  114   /* Initialize trace system early  so we can see what is going on.
  115      This logic was moved away from a constructor to this initialization
  116      routine because we want to avoid initializing the trace library for
  117      processes that suck in the IMMA libraries as a side effect of the
  118      build system, but actually never use it.
  119    */
  120   if ((value = getenv("IMMA_TRACE_PATHNAME")) && !trace_category_get()) {
  121     /* IMMA_TRACE_PATHNAME is defined and trace is not already initialized. */
  122     if (logtrace_init("imma", value, CATEGORY_ALL) != 0) {
  123       LOG_WA(
  124           "Failed to initialize trace to %s in IMMA "
  125           "library",
  126           value);
  127       /* error, we cannot do anything */
  128     }
  129     LOG_NO("IMMA library TRACE initialize done pid:%u svid:%u file:%s",
  130            getpid(), sv_id, value);
  131   }
  132 
  133   /* initialize the imma cb lock */
  134   if (m_NCS_LOCK_INIT(&cb->cb_lock) != NCSCC_RC_SUCCESS) {
  135     TRACE_4("Failed to get cb lock");
  136     goto lock_init_fail;
  137   }
  138   imma_cb.clmMemberNode = true;
  139 
  140   /* Initalize the IMMA Trees & Linked lists */
  141   rc = imma_db_init(cb);
  142   if (rc != NCSCC_RC_SUCCESS) {
  143     /* No need to log here, already logged in imma_db_init */
  144     goto db_init_fail;
  145   }
  146 
  147   if (cb->sv_id != 0) {
  148     /*The osafassert below seems to occurr sometimes on some systems. */
  149     LOG_WA("cb->sv_id is NOT ZERO (%x) on first time entry IMMA svid:%x",
  150             cb->sv_id, sv_id);
  151   }
  152 
  153   cb->sv_id = sv_id;
  154 
  155   if (m_NCS_LOCK_INIT(&cb->immnd_sync_lock) != NCSCC_RC_SUCCESS) {
  156     TRACE_4("Failed to get immnd_sync_lock lock");
  157     goto mds_reg_fail;
  158   }
  159 
  160   /* register with MDS */
  161   if (imma_mds_register(cb) != NCSCC_RC_SUCCESS) {
  162     /* No need to log here, already logged in imma_mds_register  */
  163     goto mds_reg_fail;
  164   }
  165 
  166   if (imma_sync_with_immnd(cb) != NCSCC_RC_SUCCESS) {
  167     /* Needed to prevent endless TRY_AGAIN loop for first client. */
  168     goto edu_init_fail;
  169   }
  170 
  171   /* EDU initialisation ABT: Dont exactly know why we need this but... */
  172   if (m_NCS_EDU_HDL_INIT(&cb->edu_hdl) != NCSCC_RC_SUCCESS) {
  173     TRACE_3("Failed to initialize EDU handle");
  174     goto edu_init_fail;
  175   }
  176 
  177   TRACE("Client agent successfully initialized");
  178   return NCSCC_RC_SUCCESS;
  179 
  180 edu_init_fail:
  181   /*MDS unregister */
  182   imma_mds_unregister(cb);
  183 
  184 mds_reg_fail:
  185   imma_db_destroy(cb);
  186 
  187 db_init_fail:
  188   /* destroy the lock */
  189   m_NCS_LOCK_DESTROY(&cb->cb_lock);
  190 
  191 lock_init_fail:
  192 
  193   return NCSCC_RC_FAILURE;
  194 }
  195 
  196 /****************************************************************************
  197   Name          : imma_destroy
  198 
  199   Description   : This routine destroys the IMMA control block.
  200 
  201   Arguments     : destroy_info - ptr to the destroy info
  202 
  203   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
  204 
  205   Notes         : None
  206 ******************************************************************************/
  207 static uint32_t imma_destroy(NCSMDS_SVC_ID sv_id) {
  208   IMMA_CONTINUATION_RECORD *cont, *tmp;
  209   IMMA_CB *cb = &imma_cb;
  210   TRACE_ENTER();
  211 
  212   if (mds_auth_server_disconnect(imma_sockname, cb->imma_mds_adest, sv_id,
  213                                  10000) != NCSCC_RC_SUCCESS) {
  214     // this will fail in the resurrect case, don't log
  215     TRACE("%s: mds_auth_server_disconnect failed", __FUNCTION__);
  216   }
  217 
  218   /* MDS unregister. */
  219   imma_mds_unregister(cb);
  220 
  221   m_NCS_EDU_HDL_FLUSH(&cb->edu_hdl);
  222 
  223   /* Destroy the IMMA database */
  224   osafassert(cb->sv_id == sv_id);
  225   imma_db_destroy(cb);
  226 
  227   /* destroy the lock */
  228   m_NCS_LOCK_DESTROY(&cb->cb_lock);
  229 
  230   /* free possibly stored continuations */
  231   for (cont = cb->imma_continuations; cont != NULL;) {
  232     tmp = cont;
  233     cont = tmp->next;
  234     free(tmp);
  235   }
  236 
  237   /* and wipe what remains */
  238   memset(cb, 0, sizeof(*cb));
  239 
  240   return NCSCC_RC_SUCCESS;
  241 }
  242 
  243 /****************************************************************************
  244   Name          :  imma_startup
  245 
  246   Description   :  This routine creates a IMMSv agent infrastructure to
  247                    interface with IMMSv service. Once the infrastructure is
  248                    created from then on use_count is incremented for every
  249                    startup request.
  250 
  251   Arguments     :  sv_id - service id, either NCSMDS_SVC_ID_IMMA_OM or
  252                            NCSMDS_SVC_ID_IMMA_OI.
  253 
  254   Return Values :  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
  255 
  256   Notes         :  None
  257 ******************************************************************************/
  258 unsigned int imma_startup(NCSMDS_SVC_ID sv_id) {
  259   unsigned int rc = NCSCC_RC_SUCCESS;
  260 
  261   TRACE_ENTER();
  262 
  263   int pt_err = pthread_mutex_lock(&imma_agent_lock);
  264   if (pt_err) {
  265     TRACE_4("Could not obtain mutex lock error(%u):%s", pt_err,
  266             strerror(pt_err));
  267     rc = NCSCC_RC_FAILURE;
  268     goto done_nolock;
  269   }
  270 
  271   TRACE("use count %u", imma_use_count);
  272 
  273   if (imma_use_count > 0) {
  274     /* Already created, so just increment the use_count */
  275     imma_use_count++;
  276     goto done;
  277   }
  278 
  279   if ((rc = ncs_agents_startup()) != NCSCC_RC_SUCCESS) {
  280     TRACE_3("Agents_startup failed");
  281     goto done;
  282   }
  283 
  284   /* Init IMMA */
  285   if ((rc = imma_create(sv_id)) != NCSCC_RC_SUCCESS) {
  286     TRACE_3("Failure in startup of client agent");
  287     ncs_agents_shutdown();
  288     goto done;
  289   } else {
  290     imma_use_count = 1;
  291   }
  292 
  293 done:
  294   TRACE_LEAVE2("use count %u", imma_use_count);
  295   pt_err = pthread_mutex_unlock(&imma_agent_lock);
  296   if (pt_err) {
  297     TRACE_4("Could not release mutex lock error(%u):%s", pt_err,
  298             strerror(pt_err));
  299     rc = NCSCC_RC_FAILURE;
  300   }
  301 
  302 done_nolock:
  303   return rc;
  304 }
  305 
  306 /****************************************************************************
  307   Name          :  imma_shutdown
  308 
  309   Description   :  This routine destroys the IMMSv agent infrastructure used
  310                    to interface IMMSv service. If the registered users
  311                    are > 1, it just decrements the use_count.
  312 
  313   Arguments     :  - NIL -
  314 
  315   Return Values :  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
  316 
  317   Notes         :  None
  318 ******************************************************************************/
  319 unsigned int imma_shutdown(NCSMDS_SVC_ID sv_id) {
  320   uint32_t rc = NCSCC_RC_SUCCESS;
  321 
  322   TRACE_ENTER();
  323   int pt_err = pthread_mutex_lock(&imma_agent_lock);
  324   if (pt_err) {
  325     TRACE_4("Could not obtain mutex lock error(%u):%s", pt_err,
  326             strerror(pt_err));
  327     rc = NCSCC_RC_FAILURE;
  328     goto done_nolock;
  329   }
  330 
  331   TRACE("use count %u", imma_use_count);
  332 
  333   if (imma_use_count > 1) {
  334     /* Users still exist, just decrement the use count */
  335     imma_use_count--;
  336   } else if (imma_use_count == 1) {
  337     rc = imma_destroy(sv_id);
  338     ncs_agents_shutdown();
  339     imma_use_count = 0;
  340   }
  341 
  342   TRACE_LEAVE2("use count %u", imma_use_count);
  343   pt_err = pthread_mutex_unlock(&imma_agent_lock);
  344   if (pt_err) {
  345     TRACE_4("Could not release mutex lock error(%u):%s", pt_err,
  346             strerror(pt_err));
  347     rc = NCSCC_RC_FAILURE;
  348   }
  349 
  350 done_nolock:
  351   return rc;
  352 }
  353 
  354 void imma_freeAttrValue3(SaImmAttrValueT p,
  355                          const SaImmValueTypeT attrValueType) {
  356   SaAnyT *saAnyTp = NULL;
  357   SaStringT *saStringTp = NULL;
  358 
  359   switch (attrValueType) {
  360     case SA_IMM_ATTR_SAINT32T:
  361     case SA_IMM_ATTR_SAUINT32T:
  362     case SA_IMM_ATTR_SAINT64T:
  363     case SA_IMM_ATTR_SAUINT64T:
  364     case SA_IMM_ATTR_SATIMET:
  365     case SA_IMM_ATTR_SAFLOATT:
  366     case SA_IMM_ATTR_SADOUBLET:
  367       break;
  368 
  369     case SA_IMM_ATTR_SANAMET:
  370       osaf_extended_name_free((SaNameT *)p);
  371       break;
  372 
  373     case SA_IMM_ATTR_SASTRINGT:
  374       saStringTp = (SaStringT *)p;
  375       free(*saStringTp);
  376       break;
  377     case SA_IMM_ATTR_SAANYT:
  378       saAnyTp = (SaAnyT *)p;
  379       free(saAnyTp->bufferAddr);
  380       break;
  381 
  382     default:
  383       TRACE_4(
  384           "Incorrect value for SaImmValueTypeT:%u. "
  385           "Did you forget to set the attrValueType member in a "
  386           "SaImmAttrValuesT_2 value ?",
  387           attrValueType);
  388       abort();
  389   }
  390 
  391   free(p);
  392 }
  393 
  394 void imma_copyAttrValue(IMMSV_EDU_ATTR_VAL *p,
  395                         const SaImmValueTypeT attrValueType,
  396                         const SaImmAttrValueT attrValue) {
  397   /*
  398     Copies ONE attribute value.
  399     Multivalued attributes need to copy each value.
  400   */
  401   SaUint32T valueSize = 0;
  402 
  403   SaAnyT *saAnyTp = 0;
  404   SaNameT *saNameTp = 0;
  405   SaStringT *saStringTp = 0;
  406 
  407   switch (attrValueType) {
  408     case SA_IMM_ATTR_SAINT32T:
  409       p->val.saint32 = *((SaInt32T *)attrValue);
  410       return;
  411     case SA_IMM_ATTR_SAUINT32T:
  412       p->val.sauint32 = *((SaUint32T *)attrValue);
  413       return;
  414     case SA_IMM_ATTR_SAINT64T:
  415       p->val.saint64 = *((SaInt64T *)attrValue);
  416       return;
  417     case SA_IMM_ATTR_SAUINT64T:
  418       p->val.sauint64 = *((SaUint64T *)attrValue);
  419       return;
  420     case SA_IMM_ATTR_SATIMET:
  421       p->val.satime = *((SaTimeT *)attrValue);
  422       return;
  423     case SA_IMM_ATTR_SAFLOATT:
  424       p->val.safloat = *((SaFloatT *)attrValue);
  425       return;
  426     case SA_IMM_ATTR_SADOUBLET:
  427       p->val.sadouble = *((SaDoubleT *)attrValue);
  428       return;
  429 
  430     case SA_IMM_ATTR_SANAMET:
  431       saNameTp = (SaNameT *)attrValue;
  432       valueSize = saNameTp ? osaf_extended_name_length(saNameTp) + 1 : 0;
  433       break;
  434 
  435     case SA_IMM_ATTR_SASTRINGT:
  436       /*TODO: I should have some form of sanity check on length. */
  437       saStringTp = (SaStringT *)attrValue;
  438       valueSize = (saStringTp) ? strlen(*(saStringTp)) + 1 : 0;
  439       break;
  440 
  441     case SA_IMM_ATTR_SAANYT:
  442       saAnyTp = (SaAnyT *)attrValue;
  443       if (saAnyTp)
  444         valueSize = (saAnyTp->bufferAddr) ? (saAnyTp->bufferSize + 1) : 0;
  445       else
  446         valueSize = 0;
  447       break;
  448 
  449     default:
  450       TRACE_4(
  451           "Incorrect value for SaImmValueTypeT:%u. "
  452           "Did you forget to set the attrValueType member in a "
  453           "SaImmAttrValuesT_2 value ?\n",
  454           attrValueType);
  455       abort();
  456   }
  457 
  458   p->val.x.size = valueSize;
  459   p->val.x.buf = (valueSize) ? (char *)malloc(valueSize) : NULL;
  460 
  461   if (attrValue && valueSize) {
  462     switch (attrValueType) {
  463       case SA_IMM_ATTR_SASTRINGT:
  464         (void)memcpy(p->val.x.buf, *saStringTp, valueSize);
  465         break;
  466       case SA_IMM_ATTR_SANAMET:
  467         (void)memcpy(p->val.x.buf, osaf_extended_name_borrow(saNameTp),
  468                      valueSize - 1);
  469         break;
  470       case SA_IMM_ATTR_SAANYT:
  471         (void)memcpy(p->val.x.buf, saAnyTp->bufferAddr, valueSize - 1);
  472         break;
  473       default:
  474         abort(); /*If I get here then I have introduced a bug
  475                    somewhere above. */
  476     }
  477     p->val.x.buf[valueSize - 1] = '\0';
  478   } else {
  479     abort();
  480   }
  481 }
  482 
  483 SaImmAttrValueT imma_copyAttrValue3(const SaImmValueTypeT attrValueType,
  484                                     IMMSV_EDU_ATTR_VAL *attrValue) {
  485   /*
  486     Copies ONE attribute value.
  487     Multivalued attributes need to copy each value.
  488     Allocates the root value on the heap.
  489     WARNING!, for dynamic/large sized data (SaStringT, SaAnyT) the buffer
  490     is stolen from the attrValue.
  491   */
  492   size_t valueSize = 0;
  493   SaAnyT *saAnyTp = 0;
  494   SaNameT *saNameTp = 0;
  495   SaStringT *saStringTp = 0;
  496   SaImmAttrValueT retVal = NULL;
  497 
  498   switch (attrValueType) {
  499     case SA_IMM_ATTR_SAINT32T:
  500       valueSize = sizeof(SaInt32T);
  501       break;
  502     case SA_IMM_ATTR_SAUINT32T:
  503       valueSize = sizeof(SaUint32T);
  504       break;
  505     case SA_IMM_ATTR_SAINT64T:
  506       valueSize = sizeof(SaInt64T);
  507       break;
  508     case SA_IMM_ATTR_SAUINT64T:
  509       valueSize = sizeof(SaUint64T);
  510       break;
  511     case SA_IMM_ATTR_SATIMET:
  512       valueSize = sizeof(SaTimeT);
  513       break;
  514     case SA_IMM_ATTR_SAFLOATT:
  515       valueSize = sizeof(SaFloatT);
  516       break;
  517     case SA_IMM_ATTR_SADOUBLET:
  518       valueSize = sizeof(SaDoubleT);
  519       break;
  520     case SA_IMM_ATTR_SANAMET:
  521       valueSize = sizeof(SaNameT);
  522       break;
  523     case SA_IMM_ATTR_SASTRINGT:
  524       valueSize = sizeof(SaStringT);
  525       break;
  526     case SA_IMM_ATTR_SAANYT:
  527       valueSize = sizeof(SaAnyT);
  528       break;
  529 
  530     default:
  531       TRACE_4("Illegal value type: %u", attrValueType);
  532       abort();
  533   }
  534 
  535   retVal = calloc(1, valueSize);
  536 
  537   switch (attrValueType) {
  538     case SA_IMM_ATTR_SAINT32T:
  539       *((SaInt32T *)retVal) = attrValue->val.saint32;
  540       break;
  541     case SA_IMM_ATTR_SAUINT32T:
  542       *((SaUint32T *)retVal) = attrValue->val.sauint32;
  543       break;
  544     case SA_IMM_ATTR_SAINT64T:
  545       *((SaInt64T *)retVal) = attrValue->val.saint64;
  546       break;
  547     case SA_IMM_ATTR_SAUINT64T:
  548       *((SaUint64T *)retVal) = attrValue->val.sauint64;
  549       break;
  550     case SA_IMM_ATTR_SATIMET:
  551       *((SaTimeT *)retVal) = attrValue->val.satime;
  552       break;
  553     case SA_IMM_ATTR_SAFLOATT:
  554       *((SaFloatT *)retVal) = attrValue->val.safloat;
  555       break;
  556     case SA_IMM_ATTR_SADOUBLET:
  557       *((SaDoubleT *)retVal) = attrValue->val.sadouble;
  558       break;
  559 
  560     case SA_IMM_ATTR_SANAMET:
  561       saNameTp = (SaNameT *)retVal;
  562       /* Steal the buffer. */
  563       if (attrValue->val.x.size) {
  564         osaf_extended_name_steal(attrValue->val.x.buf, saNameTp);
  565         attrValue->val.x.buf = NULL;
  566         attrValue->val.x.size = 0;
  567       } else {
  568         osaf_extended_name_clear(saNameTp);
  569       }
  570       break;
  571 
  572     case SA_IMM_ATTR_SASTRINGT:
  573       saStringTp = (SaStringT *)retVal; /*pointer TO string-pointer. */
  574       /* Steal the buffer. */
  575       if (attrValue->val.x.size) {
  576         (*saStringTp) = attrValue->val.x.buf;
  577         attrValue->val.x.buf = NULL;
  578         attrValue->val.x.size = 0;
  579       } else {
  580         (*saStringTp) = NULL;
  581       }
  582       break;
  583 
  584     case SA_IMM_ATTR_SAANYT:
  585       saAnyTp = (SaAnyT *)retVal;
  586       /*Steal the value buffer. */
  587       saAnyTp->bufferSize = attrValue->val.x.size;
  588       if (attrValue->val.x.size) {
  589         /*Steal the buffer. */
  590         saAnyTp->bufferSize = attrValue->val.x.size - 1;
  591         saAnyTp->bufferAddr = (SaUint8T *)attrValue->val.x.buf;
  592         attrValue->val.x.buf = NULL;
  593         attrValue->val.x.size = 0;
  594       } else {
  595         saAnyTp->bufferSize = 0;
  596         saAnyTp->bufferAddr = NULL;
  597       }
  598       break;
  599 
  600     default:
  601       abort();
  602   }
  603   return retVal;
  604 }
  605 
  606 SaTimeT imma_getSyncrTimeout() {
  607   SaTimeT syncr_timeout = IMMSV_WAIT_TIME;
  608   char *timeout_env_value = NULL;
  609 
  610   if ((timeout_env_value = getenv("IMMA_SYNCR_TIMEOUT"))) {
  611     syncr_timeout = atoll(timeout_env_value);
  612     if (syncr_timeout < NCS_SAF_MIN_ACCEPT_TIME) {
  613       LOG_WA("Invalid IMMA_SYNCR_TIMEOUT environment variable");
  614       syncr_timeout = NCS_SAF_MIN_ACCEPT_TIME;
  615     }
  616   }
  617   return syncr_timeout;
  618 }