Пример #1
0
static qdb_sQue *
addQueue (
  qdb_sAppl	*ap,
  qcom_tQix	qix,
  char		*name,
  qdb_eQue	type,
  pwr_tBitMask	flags
)
{
  pwr_tStatus	sts;
  qcom_sQid	qid;
  qdb_sQue	*qp;

  qid.nid = qdb->g->nid;
  qid.qix = qix;
  qp = qdb_AddQue(&sts, qix);
  if (qp == NULL) errh_Bugcheck(sts, "qdb_AddQue(&sts, &qid)");
  qp->type = type;
  qp->flags.m = flags;
  strcpy(qp->name, name);                    

  if (qp->flags.b.broadcast) {
    qdb_AddBond(&sts, qp, qdb->exportque);
  }

  if (ap != NULL) {
    pool_QinsertPred(&sts, &qdb->pool, &qp->que_ll, &ap->que_lh);
    qp->aid = ap->aid;
  }

  return qp;
}
Пример #2
0
/**
 * Adds a remote class volume.
 */
void cvolcm_AddClassVolume(
    pwr_tStatus* sts, gdb_sNode* np, const net_sGvolume* vp)
{
  gdb_sCclassVolume *ccvp, *rp;
  gdb_sVolume* cvp;

  gdb_AssumeLocked;
  pwr_Assert(vp != NULL);

  ccvp = pool_Alloc(sts, gdbroot->pool, sizeof(*ccvp));
  if (ccvp == NULL)
    return;

  ccvp->key.nid = vp->nid;
  ccvp->key.vid = vp->vid;
  ccvp->time = net_NetTimeToTime(&vp->time);

  cvp = hash_Search(sts, gdbroot->vid_ht, &vp->vid);
  if (cvp == NULL) /* This volume doesn't exist locally, but we may create it
                      later on */
    ccvp->equalClasses = 0;
  else {
    pwr_tTime t = net_NetTimeToTime(&cvp->g.time);
    ccvp->equalClasses = time_Acomp(&ccvp->time, &t) == 0 ? 1 : 0;
  }

  rp = hash_Insert(sts, gdbroot->ccvol_ht, ccvp);
  if (rp == NULL) { /* This was previously a bugcheck but obviously can occur */
    pool_Free(NULL, gdbroot->pool, ccvp);
    return;
  }

  pool_QinsertPred(NULL, gdbroot->pool, &ccvp->ccvol_ll, &np->ccvol_lh);
}
Пример #3
0
static san_sServer* addServer(
    pwr_tStatus* sts, gdb_sNode* np, gdb_sObject* op, net_sSanEntry* ep)
{
  san_sServer* sp;

  sp = hash_Search(NULL, gdbroot->sans_ht, &ep->sid);
  if (sp != NULL)
    return sp;

  sp = pool_Alloc(sts, gdbroot->pool, sizeof(san_sServer));
  if (sp == NULL)
    return NULL;

  sp->sane = *ep;
  sp = hash_Insert(sts, gdbroot->sans_ht, sp);
  if (sp == NULL)
    return NULL;
  /* To do !!!! This is a pool leak !!!!!! */

  if (gdbroot->is_tmon)
    sp->op = op;
  pool_QinsertPred(NULL, gdbroot->pool, &sp->sansAct_ll, &np->sansAct_lh);
  sp->flags.b.sansAct = 1;
  np->sansAct_lc++;
  np->sans_gen++;

  return checkServer(np, sp);
}
Пример #4
0
gdb_sNode *
gdb_AddNode (
  pwr_tStatus		*sts,
  pwr_tNodeId		nid,  
  pwr_tBitMask		flags
)
{
  gdb_sNode		*np;

  gdb_AssumeLocked;

  np = hash_Search(sts, gdbroot->nid_ht, &nid);
  if (np != NULL) return np;
  if (np != NULL) {
    if (flags & gdb_mAdd_failIfAdded)
      pwr_Return(NULL, sts, GDB__DUPLADD);
    else
      pwr_Return(np, sts, GDB__ALRADD);
  }

  np = pool_Alloc(sts, gdbroot->pool, sizeof(*np));
  if (np == NULL) return NULL;

  np->nid = nid;
  np->buf_id = 1; /* Next available buffer id */

  pool_Qinit(NULL, gdbroot->pool, &np->nid_htl);
  pool_Qinit(NULL, gdbroot->pool, &np->nod_ll);
  pool_Qinit(NULL, gdbroot->pool, &np->own_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->ccvol_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->nodms_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->nodmo_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->subc_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->nodsubs_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->nodsubb_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->sansAct_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->sansUpd_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->sancAdd_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->sancRem_lh);
  pool_Qinit(NULL, gdbroot->pool, &np->sancAct_lh);

  pool_Qinit(NULL, gdbroot->pool, &np->cacheNode.lh);
#if defined OS_ELN
  np->cacheNode.lc_max = 100;
#else
  np->cacheNode.lc_max = 200;
#endif

  np->cacheNode.flags.b.cacheNode = 1;
  np->cacheNode.next = pool_Reference(NULL, gdbroot->pool, &gdbroot->db->cacheCom);

  np = hash_Insert(sts, gdbroot->nid_ht, np);
  if (np == NULL) errh_Bugcheck(GDH__WEIRD, "adding new node");

  pool_QinsertPred(NULL, gdbroot->pool, &np->nod_ll, &gdbroot->db->nod_lh);

  return np;
}
Пример #5
0
pwr_tBoolean sanc_Subscribe(pwr_tStatus* sts, gdb_sObject* op)
{
  gdb_sVolume* vp;
  gdb_sNode* np;

  if (sts != NULL)
    *sts = 1;

  gdb_AssumeLocked;

  if (op->l.flags.b.isNative)
    pwr_Return(NO, sts, SAN__NATIVE);

  if (op->u.c.flags.m & (gdb_mCo_sancAdd | gdb_mCo_sancAct)) {
    op->u.c.sanexp = 0;
    return YES;
  }

  vp = pool_Address(NULL, gdbroot->pool, op->l.vr);
  np = pool_Address(NULL, gdbroot->pool, vp->l.nr);

  if (op->u.c.flags.b.sancRem) {
    pool_Qremove(NULL, gdbroot->pool, &op->u.c.sanc_ll);
    op->u.c.flags.b.sancRem = 0;
    pwr_Assert(np->sancRem_lc != 0);
    np->sancRem_lc--;
    pool_QinsertPred(NULL, gdbroot->pool, &op->u.c.sanc_ll, &np->sancAct_lh);
    op->u.c.flags.b.sancAct = 1;
    np->sancAct_lc++;
    return YES;
  }

  pwr_Assert(!pool_QisLinked(NULL, gdbroot->pool, &op->u.c.sanc_ll));

  pool_QinsertPred(NULL, gdbroot->pool, &op->u.c.sanc_ll, &np->sancAdd_lh);
  op->u.c.flags.b.sancAdd = 1;
  memset(&op->l.al, 0, sizeof(op->l.al));
  np->sancAdd_lc++;
  ++gdbroot->db->sancid.rix;
  op->u.c.sanid = gdbroot->db->sancid;
  op->u.c.sanexp = 0;

  return YES;
}
Пример #6
0
static void lockMountServers(gdb_sNode* np)
{
  pwr_tStatus sts;
  pool_sQlink* msl;
  pool_sQlink* vl;
  gdb_sVolume* vp;
  gdb_sMountServer* msp;
  gdb_sObject* op;

  gdb_AssumeLocked;

  for (vl = pool_Qsucc(NULL, gdbroot->pool, &np->own_lh); vl != &np->own_lh;
       vl = pool_Qsucc(NULL, gdbroot->pool, vl)) {
    vp = pool_Qitem(vl, gdb_sVolume, l.own_ll);

    if (vl->self == vl->flink) {
      /* Connection lost and volume removed from own list */
      errh_Error("Volume not owned any more, %s", vp->g.name.orig);
      return;
    }
    if (!vp->l.flags.b.isConnected) {
      /* !!! Todo !!! How do we make this known ?  */
      errh_Error("Volume not connected, %s", vp->g.name.orig);
      continue;
    }

    for (msl = pool_Qsucc(NULL, gdbroot->pool, &vp->l.volms_lh);
         msl != &vp->l.volms_lh; msl = pool_Qsucc(NULL, gdbroot->pool, msl)) {
      msp = pool_Qitem(msl, gdb_sMountServer, volms_ll);
      op = hash_Search(&sts, gdbroot->oid_ht, &msp->oid);
      if (op == NULL) {
        op = cvolc_OidToObject(
            &sts, vp, msp->oid, vol_mTrans_none, cvol_eHint_none);
        if (op == NULL) {
          errh_Error("Can't fetch the mount server's object, %s",
              cdh_ObjidToString(msp->oid, 0));
          /* !!! Todo !!! How do we make this error known ?  */
          continue;
        }
      }
      msp->msor = pool_ItemReference(NULL, gdbroot->pool, op);
      op->l.flags.b.isMountServer = 1;
      if (msp->nodms_ll.self == msp->nodms_ll.flink
          && msp->nodms_ll.self == msp->nodms_ll.blink)
        pool_QinsertPred(NULL, gdbroot->pool, &msp->nodms_ll, &np->nodms_lh);

      /* if (0)
        errh_Info("Locking object %s", op->g.f.name.orig); */
      cvolc_LockObject(&sts, op);
    }
  }
}
Пример #7
0
static void
activateTimeoutWatch (
    sub_sClient		*cp
)
{

    gdb_AssumeLocked;

    /* Handle only remotely located objects with a tmo != 0.  */

    if ((!cp->tmoactive) && (cp->nid != pwr_cNNodeId) && (cp->tmo != 0)) {
        pool_QinsertPred(NULL, gdbroot->pool, &cp->subt_ll, &gdbroot->db->subt_lh);
        cp->tmoactive = TRUE;
        gdbroot->db->subt_lc++;
    }
}
Пример #8
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);
  }
}
Пример #9
0
void
subc_CancelUser (
    pid_t			subscriber
)
{
    sub_sClient		*cp;
    pool_sQlink		*cl;
    gdb_sNode		*np;
    pool_sQlink		*nl;
    pool_sQlink		*lh;

    /* Allocate a temporary root */

    gdb_AssumeLocked;

    lh = pool_Qalloc(NULL, gdbroot->pool);

    /* Build a list with all clients to cancel */

    for (
        nl = pool_Qsucc(NULL, gdbroot->pool, &gdbroot->db->nod_lh);
        nl != &gdbroot->db->nod_lh;
        nl = pool_Qsucc(NULL, gdbroot->pool, nl)
    ) {
        np = pool_Qitem(nl, gdb_sNode, nod_ll);

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

            if (cp->subscriber == subscriber) {
                pool_Qremove(NULL, gdbroot->pool, &cp->subc_ll);
                pool_QinsertPred(NULL, gdbroot->pool, &cp->subc_ll, lh);
            }
        } /* For all clients of that node. */
    } /* For all nodes */

    /* Now cancel them all! */

    subc_CancelList(lh);

    /* Return the root to the pool */

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

}
Пример #10
0
sub_sClient *
subc_Create (
    char			*name,			/* Input or NULL */
    pwr_sAttrRef		*arp,			/* Input or NULL */
    pool_sQlink		*lh			/* List header. */
)
{
    sub_sClient		*cp;
    sub_sClient		*rcp;
    pwr_tInt32		s;
    pwr_tStatus		sts;

    gdb_AssumeLocked;

    s = sizeof(*cp) + (name == NULL ? 0 : strlen (name));
    cp = pool_Alloc(NULL, gdbroot->pool, s);

    cp->sub_by_name = (name != NULL);
    if (cp->sub_by_name)
        strcpy(cp->name, name);
    else
        cp->aref = *arp;

    cp->subscriber  = gdbroot->my_pid;
    cp->dt	  = default_dt;
    cp->tmo	  = default_tmo;
    cp->old	  = TRUE;	/* No data yet */

    /* The client is always counted in a np->subc_lc quota
       and must always be in a pool_sQlink list.  */

    pool_QinsertPred(NULL, gdbroot->pool, &cp->subc_ll, lh);
    gdbroot->no_node->subc_lc++;

    do {
        gdbroot->db->subcid.rix++;
        cp->sid = gdbroot->db->subcid;

        rcp = hash_Insert(&sts, gdbroot->subc_ht, cp);
        if (rcp != cp && sts != HASH__DUPLICATE)
            errh_Bugcheck(sts, "hash_Insert");
    } while (rcp != cp);

    return cp;
}
Пример #11
0
gdb_sAliasServer *
gdb_AddAliasServer (
  pwr_tStatus		*sts,
  pwr_tObjid		soid,
  pwr_tBitMask		flags
)
{
  gdb_sAliasServer	*asp;
  gdb_sObject		*op = NULL;

  gdb_AssumeLocked;

  pwr_Assert(cdh_ObjidIsNotNull(soid));

  asp = hash_Search(sts, gdbroot->as_ht, &soid);
  if (asp != NULL) {
    if (flags & gdb_mAdd_failIfAdded) 
      pwr_Return(NULL, sts, GDB__DUPLADD);
    else
      pwr_Return(asp, sts, GDB__ALRADD);
  }

  asp = pool_Alloc(sts, gdbroot->pool, sizeof(*asp));
  if (asp == NULL) return NULL;

  asp->oid = soid;

  pool_Qinit(NULL, gdbroot->pool, &asp->as_htl);
  pool_Qinit(NULL, gdbroot->pool, &asp->as_ll);
  pool_Qinit(NULL, gdbroot->pool, &asp->cli_lh);

  asp = hash_Insert(sts, gdbroot->as_ht, asp);
  if (asp == NULL) errh_Bugcheck(GDH__WEIRD, "adding new alias server");

  pool_QinsertPred(NULL, gdbroot->pool, &asp->as_ll, &gdbroot->db->as_lh);

  op = hash_Search(sts, gdbroot->oid_ht, &soid);
  if (op == NULL) errh_Bugcheck(GDH__WEIRD, "getting alias server object");
  
  op->g.flags.b.isAliasServer = 1;

  return asp;
}
Пример #12
0
gdb_sMountServer *
gdb_AddMountServer (
  pwr_tStatus		*sts,
  pwr_tObjid		soid,
  pwr_tBitMask		flags
)
{
  gdb_sMountServer	*msp;

  gdb_AssumeLocked;

  // pwr_Assert(cdh_ObjidIsNotNull(soid));
  if (cdh_ObjidIsNull(soid)) return NULL;

  msp = hash_Search(sts, gdbroot->ms_ht, &soid);
  if (msp != NULL) {
    if (flags & gdb_mAdd_failIfAdded)
      pwr_Return(NULL, sts, GDB__DUPLADD);
    else
      pwr_Return(msp, sts, GDB__ALRADD);
  }

  msp = pool_Alloc(sts, gdbroot->pool, sizeof(*msp));
  if (msp == NULL) return NULL;

  msp->oid = soid;

  pool_Qinit(NULL, gdbroot->pool, &msp->ms_htl);
  pool_Qinit(NULL, gdbroot->pool, &msp->ms_ll);
  pool_Qinit(NULL, gdbroot->pool, &msp->nodms_ll);
  pool_Qinit(NULL, gdbroot->pool, &msp->volms_ll);
  pool_Qinit(NULL, gdbroot->pool, &msp->cli_lh);

  msp = hash_Insert(sts, gdbroot->ms_ht, msp);
  if (msp == NULL) errh_Bugcheck(GDH__WEIRD, "adding new mount server");

  pool_QinsertPred(NULL, gdbroot->pool, &msp->ms_ll, &gdbroot->db->ms_lh);

  return msp;
}
Пример #13
0
gdb_sVolume *
gdb_AddVolume (
  pwr_tStatus		*sts,
  pwr_tVolumeId		vid,
  pwr_tBitMask		flags
)
{
  gdb_sVolume		*vp;

  gdb_AssumeLocked;

  vp = hash_Search(sts, gdbroot->vid_ht, &vid);
  if (vp != NULL) {
    if (flags & gdb_mAdd_failIfAdded)
      pwr_Return(NULL, sts, GDB__DUPLADD);
    else
      pwr_Return(vp, sts, GDB__ALRADD);
  }

  vp = pool_Alloc(sts, gdbroot->pool, sizeof(*vp));
  if (vp == NULL) return NULL;

  vp->g.vid	= vid;
  vp->g.oid.vid	= vid;

  pool_Qinit(NULL, gdbroot->pool, &vp->l.vid_htl);
  pool_Qinit(NULL, gdbroot->pool, &vp->l.vn_htl);
  pool_Qinit(NULL, gdbroot->pool, &vp->l.vol_ll);
  pool_Qinit(NULL, gdbroot->pool, &vp->l.own_ll);
  pool_Qinit(NULL, gdbroot->pool, &vp->l.obj_lh);
  pool_Qinit(NULL, gdbroot->pool, &vp->l.volms_lh);

  hash_Insert(sts, gdbroot->vid_ht, vp);
  vp->l.flags.b.inVidTable = 1;

  pool_QinsertPred(sts, gdbroot->pool, &vp->l.vol_ll, &gdbroot->db->vol_lh);
  vp->l.flags.b.inVolList = 1;
  
  return vp;
}
Пример #14
0
gdb_sClass *
gdb_AddClass (
  pwr_tStatus		*sts,
  pwr_tClassId		cid,
  pwr_tBitMask		flags
)
{
  gdb_sClass		*cp;

#if 0
  pwr_Assert(cid != pwr_cNClassId);
#endif

  gdb_AssumeLocked;

  cp = hash_Search(sts, gdbroot->cid_ht, &cid);
  if (cp != NULL) {
    if (flags & gdb_mAdd_failIfAdded)
      pwr_Return(NULL, sts, GDB__DUPLADD);
    else
      pwr_Return(cp, sts, GDB__ALRADD);
  }

  cp = pool_Alloc(sts, gdbroot->pool, sizeof(*cp));
  if (cp == NULL) return NULL;

  cp->cid = cid;

  pool_Qinit(NULL, gdbroot->pool, &cp->cid_htl);
  pool_Qinit(NULL, gdbroot->pool, &cp->cid_lh);
  pool_Qinit(NULL, gdbroot->pool, &cp->class_ll);

  cp = hash_Insert(sts, gdbroot->cid_ht, cp);
  if (cp == NULL) errh_Bugcheck(GDH__WEIRD, "adding new class");

  pool_QinsertPred(NULL, gdbroot->pool, &cp->class_ll, &gdbroot->db->class_lh);

  return cp;
}
Пример #15
0
void
sancm_MoveExpired (
    pwr_tStatus		*status,
    gdb_sNode		*np
)
{
    pool_sQlink		*ol;
    gdb_sObject		*op;

    if (status != NULL) *status = 1;

    gdb_AssumeLocked;

    if (np->sancAct_lc == 0) return;

    for (
        ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancAct_lh);
        ol != &np->sancAct_lh;
    ) {
        op = pool_Qitem(ol, gdb_sObject, u.c.sanc_ll);
        ol = pool_Qsucc(NULL, gdbroot->pool, ol);

        pwr_Assert(op->u.c.flags.b.sancAct);

        if (op->u.c.sanexp) {
            pool_Qremove(NULL, gdbroot->pool, &op->u.c.sanc_ll);
            op->u.c.flags.b.sancAct = 0;
            pwr_Assert((op->u.c.flags.m & gdb_mCo_inSancList) == 0);
            pwr_Assert(np->sancAct_lc != 0);
            np->sancAct_lc--;

            pool_QinsertPred(NULL, gdbroot->pool, &op->u.c.sanc_ll, &np->sancRem_lh);
            op->u.c.flags.b.sancRem = 1;
            np->sancRem_lc++;
            op->u.c.sanexp = 0;
        } else if (!op->l.flags.b.isMountServer)
            op->u.c.sanexp = 1;
    }
}
Пример #16
0
/**
 * Adds a remote class volume.
 */
void 
cvolcm_AddClassVolume(
  pwr_tStatus		*sts,
  gdb_sNode		*np,
  const net_sGvolume	*vp
)
{
  gdb_sCclassVolume	*ccvp;
  gdb_sVolume		*cvp;
  

  gdb_AssumeLocked;
  pwr_Assert(vp != NULL);



  ccvp = pool_Alloc(sts, gdbroot->pool, sizeof(*ccvp));
  if (ccvp == NULL) return;

  ccvp->key.nid = vp->nid;
  ccvp->key.vid = vp->vid;
  ccvp->time = net_NetTimeToTime(&vp->time);
  
  cvp = hash_Search(sts, gdbroot->vid_ht, &vp->vid);
  if (cvp == NULL) /* This volume doesn't exist locally, but we may create it later on */
    ccvp->equalClasses = 0;
  else {
    pwr_tTime t = net_NetTimeToTime( &cvp->g.time);
    ccvp->equalClasses = time_Acomp(&ccvp->time, &t) == 0 ? 1 : 0;
  }
  
  ccvp = hash_Insert(sts, gdbroot->ccvol_ht, ccvp);
  if (ccvp == NULL) errh_Bugcheck(GDH__WEIRD, "adding cached class volume");
  
  pool_QinsertPred(NULL, gdbroot->pool, &ccvp->ccvol_ll, &np->ccvol_lh);

}
Пример #17
0
static san_sServer* checkServer(gdb_sNode* np, san_sServer* sp)
{
  gdb_sObject* op;

  if (!gdbroot->is_tmon || sp->op == NULL) {
    op = hash_Search(NULL, gdbroot->oid_ht, &sp->sane.oid);
    if (op == NULL || !op->l.flags.b.isOwned) {
      removeServer(np, sp);
      return NULL;
    }
    if (gdbroot->is_tmon)
      sp->op = op;

  } else
    op = sp->op;

  if (op->l.al.idx <= sp->al.idx)
    return sp;

  if (!sp->flags.b.sansUpd) {
    pool_QinsertPred(NULL, gdbroot->pool, &sp->sansUpd_ll, &np->sansUpd_lh);
    sp->flags.b.sansUpd = 1;
  }

  if (!op->g.flags.b.isMountClient) {
    sp->al.a = op->l.al.a;
    sp->al.b = op->l.al.b;
    sp->al.maxa = op->u.n.ral.maxa;
    sp->al.maxb = op->u.n.ral.maxb;
  } else
    memset(&sp->al, 0, sizeof(sp->al));

  sp->al.idx = op->l.al.idx;

  return sp;
}
Пример #18
0
void
sancm_Add (
    pwr_tStatus		*status,
    gdb_sNode		*np
)
{
    net_sSanAdd		*ap;
    pool_sQlink		*ol;
    gdb_sObject		*op;
    int			count;
    int			i;
    qcom_sQid		tgt;

    if (status != NULL) *status = 1;

    gdb_AssumeLocked;

    if (np->sancAdd_lc == 0) return;
    count = MIN(np->sancAdd_lc, net_cSanMaxAdd);
    ap = malloc(sizeof(net_sSanAdd) + (count - 1) * sizeof(ap->sane[0]));
    if (ap == NULL) return;

    tgt.nid = np->nid;
    tgt.qix = net_cProcHandler;

    for (
        i = 0, ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancAdd_lh);
        ol != &np->sancAdd_lh;
        ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancAdd_lh)
    ) {
        op = pool_Qitem(ol, gdb_sObject, u.c.sanc_ll);

        ap->sane[i].oid = op->g.oid;
        ap->sane[i].sid = op->u.c.sanid;
        i++;
        pwr_Assert(op->u.c.flags.b.sancAdd);
        pool_Qremove(NULL, gdbroot->pool, &op->u.c.sanc_ll);
        op->u.c.flags.b.sancAdd = 0;
        pwr_Assert((op->u.c.flags.m & gdb_mCo_inSancList) == 0);
        pwr_Assert(np->sancAdd_lc != 0);
        np->sancAdd_lc--;
        pwr_Assert(!op->u.c.flags.b.sancAct);
        pool_QinsertPred(NULL, gdbroot->pool, &op->u.c.sanc_ll, &np->sancAct_lh);
        op->u.c.flags.b.sancAct = 1;
        np->sancAct_lc++;
        if (i >= count) {
            ap->count = count;
            gdb_Unlock;
            net_Put(NULL, &tgt, ap, net_eMsg_sanAdd, 0, pwr_Offset(ap, sane[i]), 0);
            gdb_Lock;
            i = 0;
        }
    }

    pwr_Assert(np->sancAdd_lc == 0);

    /* Send remaining san entries.  */

    if (i > 0) {
        ap->count = i;
        gdb_Unlock;
        net_Put(NULL, &tgt, ap, net_eMsg_sanAdd, 0, pwr_Offset(ap, sane[i]), 0);
        gdb_Lock;
    }

    free(ap);
}
Пример #19
0
void
subcm_Data (
  qcom_sGet		*get
)
{
  pwr_tStatus		sts;
  pwr_tTime		curtim;
  pool_tRef		mr;
  sub_sMessage		*mp;
  pwr_tUInt32		refcount = 0;
  pwr_tInt32		i;
  sub_sClient		*cp;
  pool_tRef		dr;
  net_sSubData		*dp;
  void			*adrs;
  gdb_sNode		*np;
  net_sSubRemove	*rp = NULL;
  qcom_sQid		tgt;
  gdb_sCclass		*ccp;
  ndc_sRemoteToNative	*tbl;
  int                   rsize;
  

  time_GetTime( &curtim);

  gdb_AssumeUnlocked;

  tgt.qix = net_cProcHandler;

  gdb_ScopeLock {

    /* Allocate space for, and store the message in the pool.  */

    mp = pool_Alloc(&sts, gdbroot->pool, sizeof(*mp) - sizeof(mp->msg) + get->size);
    if (mp == NULL) break;
    mr = pool_ItemReference(NULL, gdbroot->pool, mp);

    memcpy(&mp->msg, get->data, get->size);
    pool_Qinit(NULL, gdbroot->pool, &mp->subm_ll);
    pool_QinsertPred(NULL, gdbroot->pool, &mp->subm_ll, &gdbroot->db->subm_lh);
    gdbroot->db->subm_lc++;
    np = hash_Search(&sts, gdbroot->nid_ht, &mp->msg.hdr.nid);


    /* Check if message is corrupt */
    dp = (net_sSubData *)&mp->msg.subdata;
    for ( i=0; i < mp->msg.count; i++) {
      if ( (char *)dp > (char *)&mp->msg + get->size || (char *)dp < (char *)&mp->msg) {
	errh_Error( "Subscription client message corrupt");
	gdb_Unlock;
	return;
      }
      dp = (net_sSubData *)((unsigned long)&dp->data + dp->size);
    }

    /* Walk through every entry in the message buffer.  */
    for (
      i=0,
      dp = (net_sSubData *)&mp->msg.subdata,
      dr = mr + offsetof(sub_sMessage, msg.subdata);

      i < mp->msg.count;

      i++,
      dr += offsetof(net_sSubData, data) + (unsigned long)dp->size,
      dp = (net_sSubData *)((unsigned long)&dp->data + dp->size)
    ) {

      cp = hash_Search(&sts, gdbroot->subc_ht, &dp->sid);
      if (cp == NULL) {
	if (rp == NULL) {
	  rp = pool_Alloc(&sts, gdbroot->pool, sizeof(*rp)
	    + ((mp->msg.count - 1) * sizeof(rp->sid[0])));
	  if (rp == NULL)
	    continue;
	  tgt.nid = mp->msg.hdr.nid;
	}
	rp->sid[rp->count++] = dp->sid;
	continue;
      }

      /* If the client has an earlier reference to a message, then
	 remove that reference.
	 This can cause the old message to get disposed of.  */

      subc_RemoveFromMessage(cp);

      /* Now start filling in the client according to the new
	 information we just received...  */

      memcpy(&cp->lastupdate, &curtim, sizeof(curtim));
      cp->sts = dp->sts;
      cp->count++;

      if (ODD(dp->sts)) {
	cp->old	    = FALSE;	/* There is new, fresh, real data!  */
	cp->submsg  = mr;
	cp->subdata = dr;
	refcount++;

	if (1 || mp->msg.hdr.xdr) {
          if (cp->cclass == pool_cNRef) {
            gdb_sClass		*classp;
            cdh_uTypeId		cid;

            cid.pwr = cp->aref.Body;
            cid.c.bix = 0;	/* To get the class id.  */
            classp = hash_Search(&sts, gdbroot->cid_ht, &cid.pwr);
	    rsize = dp->size;

            if (classp != NULL)
              ndc_ConvertData(&sts, np, classp, &cp->aref, dp->data, dp->data, (pwr_tUInt32 *)&rsize, ndc_eOp_decode, cp->aref.Offset, 0);
	  }
          else {
            cp->old = TRUE;
            ccp = pool_Address(&cp->sts, gdbroot->pool, cp->cclass);
            if (ccp != NULL) {
              tbl = pool_Address(&cp->sts, gdbroot->pool, ccp->rnConv);
              if (tbl != NULL) {
	        rsize = dp->size;
                ndc_ConvertRemoteData(&cp->sts, np, ccp, &cp->raref, dp->data, dp->data, (pwr_tUInt32 *)&rsize, ndc_eOp_decode, cp->raref.Offset, 0);
                if (ODD(cp->sts))
                  cp->old = FALSE;
              }
            }
          }
          
	  /* !!! Todo !!! Error handling. */
	}

	/* If the userdata field contains a valid pool_tRef, then
	   copy the data. This poolref is resolved in RTDB!  */

	if (cp->userdata != pool_cNRef) {
	  adrs = pool_Address(NULL, gdbroot->rtdb, cp->userdata);
	  if (adrs != NULL) {
            if (cp->cclass == pool_cNRef)
              memcpy(adrs, dp->data, MIN(dp->size, cp->usersize));
            else if (!cp->old) {
              pwr_tUInt32  size = cp->usersize;
              pwr_tBoolean first = 1;
              ndc_ConvertRemoteToNativeTable(&cp->sts, ccp, tbl, &cp->raref, &cp->aref, adrs, dp->data, &size, 
                                             cp->aref.Offset, 0, 0, &first, np->nid);
              if (EVEN(cp->sts))
                cp->old = TRUE;
            }
	  }
	}
      }
    }

    /* Fill in count as the # of references in the 'message' header. This
       is the # of references that have to be removed before the 'message'
       can be returned to pool. If there are no references to the 'message'
       just dispose it!  */

    if (refcount != 0) {
      mp->msg.count = refcount;
    } else {
      pool_Qremove(NULL, gdbroot->pool, &mp->subm_ll);
      gdbroot->db->subm_lc--;
      pool_Free(NULL, gdbroot->pool, mp);
    }

  } gdb_ScopeUnlock;

  if (rp != NULL) { 
    tgt = np->handler;
    net_Put(NULL, &tgt, rp, net_eMsg_subRemove, 0, pwr_Offset(rp, sid[rp->count]), 0);
#if 0
    errh_Info("Removed %d subscriptions", rp->count - 1);
#endif
    pool_Free(NULL, gdbroot->pool, rp);
  }
}
Пример #20
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
}
Пример #21
0
gdb_sVolume *
cvolcm_ConnectVolume (
  pwr_tStatus		*sts,
  gdb_sVolume		*vp,
  net_sGvolume		*gvp,
  gdb_sNode		*np
)
{
  gdb_sTouchQ		*tqp;
  gdb_sVolume		*ovp;

  gdb_AssumeLocked;

  if (vp->g.nid != pwr_cNNodeId && vp->g.nid != np->nid) {
    errh_Error("Volume %s (%s) is loaded from another node.\nCurrent: %s, new: %s",
      vp->g.name.orig, cdh_VolumeIdToString(NULL, vp->g.vid, 1, 0),
      cdh_NodeIdToString(NULL, vp->g.nid, 1, 0),
      cdh_NodeIdToString(NULL, np->nid, 1, 0));
    return NULL;
  }

  vp->g = *gvp;

  pwr_Assert(vp->g.nid != pwr_cNNodeId);

  vp->l.nr = pool_Reference(NULL, gdbroot->pool, np);

  /* Add volume name to hash table.  */

  ovp = hash_Search(NULL, gdbroot->vn_ht, &vp->g.name);
  if (ovp != NULL) {
    if (ovp != vp) {
      errh_Warning("Volume name allready exist: %s, vid: %x\n", vp->g.name.orig, vp->g.vid);
      hash_Remove(NULL, gdbroot->vn_ht, ovp);
      ovp = hash_Insert(sts, gdbroot->vn_ht, vp);
      pwr_Assert(ovp == vp);  
    }
  } else {
    ovp = hash_Insert(sts, gdbroot->vn_ht, vp);
    pwr_Assert(ovp == vp);  
  }
  vp->l.flags.b.inVnTable = 1;

  pwr_Assert(!vp->l.flags.b.inOwnList);  
  pool_QinsertPred(sts, gdbroot->pool, &vp->l.own_ll, &np->own_lh);
  vp->l.flags.b.inOwnList = 1;

  /* Initiate touch queues.  */

  tqp = &vp->u.c.cacheLock;
  pool_Qinit(NULL, gdbroot->pool, &tqp->lh);
  tqp->lc_max = 0;
  tqp->flags.b.cacheLock = 1;
  tqp->next = pool_cNRef;

  tqp = &vp->u.c.cacheVol;
  pool_Qinit(NULL, gdbroot->pool, &tqp->lh);
#if defined OS_ELN
  tqp->lc_max = 100;
#else
  tqp->lc_max = 200;
#endif
  tqp->flags.b.cacheVol = 1;
  tqp->next = pool_Reference(NULL, gdbroot->pool, &np->cacheNode);

  vp->l.flags.b.isConnected = 1;
  vp->l.flags.b.isCached = 1;
  vp->l.flags.b.netCached = 1;
  vp->l.flags.b.remote = 1;
  
  return vp;
}