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; }
/** * 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); }
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); }
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; }
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; }
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); } } }
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++; } }
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); } }
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); }
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; }
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; }
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; }
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; }
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; }
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; } }
/** * 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); }
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; }
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); }
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); } }
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 }
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; }