Esempio n. 1
0
void
subcm_CheckTimeout ()
{
  pool_sQlink		*cl;
  sub_sClient		*cp;
  pwr_tTime		curtim;
  pwr_tTime		restim;
  pwr_tDeltaTime	tmotim;
  pwr_tInt32		n;
  pwr_tInt32		i;

  gdb_AssumeLocked;

  gdbroot->db->tmocnt++;  /* Statistics */

  time_GetTime( &curtim);

  /* Calculate # of remote object clients to process this time */

  n = gdbroot->db->subt_lc;
  if (n == 0) n = MIN(1, gdbroot->db->subt_lc);

  for (i=0; i<n; i++) {

    /* Temporarily remove the first entry from the queue for processing.  */

    cl = pool_QremoveSucc(NULL, gdbroot->pool, &gdbroot->db->subt_lh);
    cp = pool_Qitem(cl, sub_sClient, subt_ll);

    /* Find out if the client has timed out */

    if (!cp->old) {
      /* cp->tmo in 10ths of seconds */
      tmotim.tv_sec = cp->tmo / 10;
      tmotim.tv_nsec = (cp->tmo - tmotim.tv_sec * 10) * 100000000;
      time_Aadd(&restim, &cp->lastupdate, &tmotim);       

      /* curtim >= tmotim + lastupdate */
      if (time_Acomp(&curtim, &restim) >= 0) 
	subc_SetOld(cp);
    } /* If it was old already */

    /* Reinsert the entry last in the queue.  */
    
    pool_QinsertPred(NULL, gdbroot->pool, cl, &gdbroot->db->subt_lh);
  }
}
Esempio n. 2
0
void
subc_ActivateList (
    pool_sQlink		*lh,
    pwr_tObjid		oid
)
{
    pwr_tStatus		sts;
    tree_sTable		*add;
#if 0
    tree_sTable		*remove;
    sRemove		*rep;
#endif
    net_sSubSpec		*specp;
    qcom_sQid		tgt;
    pool_sQlink		*my_lh;
    pwr_tUInt32		my_subc_lc;
    gdb_sNode		*np;
    gdb_sNode		*old_np;
    sub_sClient		*cp;
    pool_sQlink		*cl;
    sAdd			*aep;


    /* Test each client. If existing object, fill in nid field
       and move the client to the appropriate nodes's subc_lh list. Turn
       on timeouts. Put request in subadd message buffer.

       We must do it all in one pass, since a user can come in during
       a cache query for a later subcli and cancel the subscription
       for an earlier subcli.  */

    add = tree_CreateTable(&sts, sizeof(pwr_tNodeId), offsetof(sAdd, nid),
                           sizeof(sAdd), 10, tree_Comp_nid);
#if 0
    remove = tree_CreateTable(&sts, sizeof(pwr_tNodeId), offsetof(sRemove, nid),
                              sizeof(sRemove), 10, tree_eComp_nid);
#endif

    /* Move all objects to a new, temporary root */

    my_lh = pool_Qalloc(NULL, gdbroot->pool);
    my_subc_lc = 0;

    for (cl = pool_Qsucc(NULL, gdbroot->pool, lh); cl != lh;) {
        cp = pool_Qitem(cl, sub_sClient, subc_ll);
        cl = pool_Qsucc(NULL, gdbroot->pool, cl);

        if (cdh_ObjidIsNull(oid) || cdh_ObjidIsEqual(oid, cp->aref.Objid)) {
            pool_Qremove(NULL, gdbroot->pool, &cp->subc_ll);
            pool_QinsertPred(NULL, gdbroot->pool, &cp->subc_ll, my_lh);
            my_subc_lc++;
        }
    }

    /* Now start testing clients from 'my_lh', and move them to other lists
       Make sure the clients are still there after the test.  */

    for (cl = pool_Qsucc(NULL, gdbroot->pool, my_lh); cl != my_lh; ) {
        cp = pool_Qitem(cl, sub_sClient, subc_ll);
        cl = pool_Qsucc(NULL, gdbroot->pool, cl);

        np = testClient(&sts, cp);

        /* If an error is returned the client doesn't exist anymore. Some
           other user removed it while TestSubcli had the database unlocked.
           Just go on with the next client...  */

        if (np == NULL) continue;

        /* Move the client to the list for the node where the object resides.
           nid = pwr_cNNodeId is used for all objects we don't know.  */

        old_np = hash_Search(&sts, gdbroot->nid_ht, &cp->nid);
        if (old_np == NULL) errh_Bugcheck(GDH__WEIRD, "");

        pool_Qremove(NULL, gdbroot->pool, &cp->subc_ll);
        old_np->subc_lc--;
        pool_QinsertPred(NULL, gdbroot->pool, &cp->subc_ll, &np->subc_lh);
        np->subc_lc++;
        cp->nid = np->nid;

        /* If the object's nid changed, then take the appropriate actions.  */

        if (np != old_np) {
            if (np->nid != pwr_cNNodeId) {  /* Object is known.  */

                activateTimeoutWatch(cp);

                aep = tree_Insert(&sts, add, &np->nid);
                if (aep == NULL) errh_Bugcheck(GDH__WEIRD, "");

                if (aep->msg == NULL) {
                    aep->cnt = MIN(my_subc_lc, net_cSubMaxAdd);
                    aep->msg = malloc(sizeof(net_sSubAdd) + sizeof(net_sSubSpec) * aep->cnt);
                    aep->msg->count = 0;
                } /* If there was no message allocated */

                specp		    = &aep->msg->spec[aep->msg->count];
                specp->sid	    = cp->sid;
                specp->dt	    = cp->dt;
                specp->sub_by_name  = cp->sub_by_name;
                specp->aref	    = cp->cclass != pool_cNRef ? cp->raref : cp->aref;

                if (++aep->msg->count >= aep->cnt) {

                    /* The message buffer is full and must be sent.  */

                    tgt = np->handler;
                    pwr_Assert(tgt.nid != pwr_cNNodeId);

                    gdb_Unlock;

                    net_Put(NULL, &tgt, aep->msg, net_eMsg_subAdd, 0, pwr_Offset(aep->msg, spec[aep->msg->count]), 0);

                    gdb_Lock;

                    aep->msg->count = 0;

                }

            } else {	/* The object became unknown... */

                cancelTimeoutWatch(cp);
                subc_SetOld(cp);	/* Data gets old immediately */

#if 0
                /** @todo Maybe we should unlock the cached class? */
                if (cp->cclass != pwr_cNRefId) {
                    ccp = pool_Address(NULL, gdbroot->pool, cp->cclass);
                    if (ccp == NULL) errh_Bugcheck(GDH__WEIRD, "Cached class address");
                    cmvolc_UnlockClass(NULL, ccp);
                    cp->cclass = pwr_cNRefId;
                }
#endif

#if 0
                if (old_np->nid != pwr_cNNodeId) {
                    rep = tree_Insert(&sts, remove, &old_np->nid);
                    if (rep == NULL) errh_Bugcheck(GDH__WEIRD, "");

                    if (rep->msg == NULL) {
                        rep->nid = old_np->nid;
                        rep->cnt = MIN(my_subc_lc, net_cSubMaxRemove);
                        rep->msg = malloc(sizeof(net_sSubRemove) + sizeof(rep->msg->sid[0]) * rep->cnt);
                        rep->msg->count = 0;
                    }

                    rep->msg->sid[rep->msg->count++] = cp->sid;

                    if (rep->msg->count >= net_cSubMaxRemove) {
                        np = hash_Search(&sts, gdbroot->nid_ht, &old_np->nid);
                        if (np == NULL) errh_Bugcheck(sts, "");
                        tgt.nid = rep->nid;
                        pwr_Assert(tgt.nid != pwr_cNNodeId);

                        gdb_Unlock;

                        net_Put(NULL, &tgt, rep->msg, net_eMsg_subRemove, 0, pwr_Offset(rep->msg, sid[rep->msg->count]), 0);

                        gdb_Lock;

                        rep->msg->count = 0;

                    }
                }
#endif
            }
        }
    }

    pool_Free(NULL, gdbroot->pool, my_lh);

    /* Now walk through the addmsg & remmsg and send all unsent messages.  */

    gdb_Unlock;

#if 0
    for (rep = tree_Minimum(remove); rep != NULL; rep = tree_Successor(remove, rep)) {
        if (rep->msg != NULL) {
            if (rep->msg->count > 0) {
                tgt.nid = rep->nid;
                pwr_Assert(tgt.nid != pwr_cNNodeId);
                net_Put(NULL, &tgt, rep->msg, net_eMsg_subRemove, 0, pwr_Offset(rep->msg, sid[rep->msg->count]), 0);
            }
            free(rep->msg);
        }
    }
#endif
    for (aep = tree_Minimum(&sts, add); aep != NULL; aep = tree_Successor(&sts, add, aep)) {
        if (aep->msg != NULL) {
            if (aep->msg->count > 0) {

                np = hash_Search(&sts, gdbroot->nid_ht, &aep->nid);
                if (np == NULL) errh_Bugcheck(GDH__WEIRD, "");

                tgt = np->handler;
                pwr_Assert(tgt.nid != pwr_cNNodeId);
                net_Put(NULL, &tgt, aep->msg, net_eMsg_subAdd, 0, pwr_Offset(aep->msg, spec[aep->msg->count]), 0);
            }
            free(aep->msg);
        }
    }

    gdb_Lock;

    tree_DeleteTable(&sts, add);
#if 0
    tree_DeleteTable(remove);
#endif
}