static void removeServer(gdb_sNode* np, san_sServer* sp) { hash_Remove(NULL, gdbroot->sans_ht, sp); if (sp->flags.b.sansAct) { pool_Qremove(NULL, gdbroot->pool, &sp->sansAct_ll); np->sansAct_lc--; np->sans_gen++; } if (sp->flags.b.sansUpd) pool_Qremove(NULL, gdbroot->pool, &sp->sansUpd_ll); pool_Free(NULL, gdbroot->pool, sp); }
void cvolsm_RemoveMountedOn ( pwr_tStatus *sts, gdb_sMountedOn *mop ) { gdb_AssumeLocked; pool_Qremove(NULL, gdbroot->pool, &mop->nodmo_ll); pool_Qremove(NULL, gdbroot->pool, &mop->volmo_ll); pool_Free(NULL, gdbroot->pool, mop); }
void cvolcm_FlushNode(pwr_tStatus* sts, gdb_sNode* np) { pool_sQlink* vl; gdb_sVolume* vp; gdb_sCclassVolume* cvp; pwr_tStatus lsts; gdb_AssumeLocked; pwr_Assert(np != gdbroot->my_node && np != gdbroot->no_node); for (vl = pool_Qsucc(NULL, gdbroot->pool, &np->own_lh); vl != &np->own_lh; vl = pool_Qsucc(NULL, gdbroot->pool, &np->own_lh)) { vp = pool_Qitem(vl, gdb_sVolume, l.own_ll); pwr_Assert(vp->l.flags.b.isCached); if (vp->l.flags.b.isCached) cvolcm_FlushVolume(NULL, vp); } for (vl = pool_Qsucc(NULL, gdbroot->pool, &np->ccvol_lh); vl != &np->ccvol_lh; vl = pool_Qsucc(NULL, gdbroot->pool, &np->ccvol_lh)) { cvp = pool_Qitem(vl, gdb_sCclassVolume, ccvol_ll); hash_Remove(&lsts, gdbroot->ccvol_ht, cvp); if (EVEN(lsts)) errh_Bugcheck(lsts, "cached class volume inconsistency"); pool_Qremove(NULL, gdbroot->pool, &cvp->ccvol_ll); pool_Free(NULL, gdbroot->pool, cvp); } }
void cvolcm_ExternVolumeFlush(gdb_sNode* np) { pool_sQlink* vl; gdb_sVolume* vp; pool_sQlink* ol; gdb_sObject* op; gdb_sMountServer* msp; pwr_tStatus sts; // Flush local node 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); pwr_Assert(vp->l.flags.b.isCached); if (vp->l.flags.b.isCached) { for (ol = pool_Qsucc(NULL, gdbroot->pool, &vp->l.obj_lh); ol != &vp->l.obj_lh; ol = pool_Qsucc(NULL, gdbroot->pool, &vp->l.obj_lh)) { op = pool_Qitem(ol, gdb_sObject, l.obj_ll); if (op->l.flags.b.isMountServer) { msp = (gdb_sMountServer*)hash_Search( &sts, gdbroot->ms_ht, &op->g.oid); if (msp == NULL) errh_Bugcheck(sts, "mount server inconsitency"); msp->msor = pool_cNRef; pool_Qremove(NULL, gdbroot->pool, &msp->nodms_ll); /* Todo !!! Clear alarm and blocklevel in all mount clients. */ } cvol_FlushObject(op); } } } }
void * hash_Remove ( pwr_tStatus *sts, hash_sTable *htp, void *ip /* Address of item to be removed. */ ) { hash_sGtable *ghtp; pool_sQlink *il; pool_sQlink *bl; ghtp = htp->ghtp; ghtp->removes++; il = findEntry(sts, &bl, htp, (char *)ip + ghtp->key_offset); if (il == NULL) return NULL; il = pool_Qremove(sts, htp->php, il); if (il == NULL) return NULL; ghtp->entries--; if (bl->flink == bl->self) ghtp->used_buckets--; pwr_Return(ip, sts, HASH__SUCCESS); }
void cvolcm_FlushVolume ( pwr_tStatus *sts, gdb_sVolume *vp ) { pool_sQlink *ol; gdb_sObject *op; gdb_sMountServer *msp; gdb_AssumeLocked; for ( ol = pool_Qsucc(NULL, gdbroot->pool, &vp->l.obj_lh); ol != &vp->l.obj_lh; ol = pool_Qsucc(NULL, gdbroot->pool, &vp->l.obj_lh) ) { op = pool_Qitem(ol, gdb_sObject, l.obj_ll); if (op->l.flags.b.isMountServer) { msp = hash_Search(sts, gdbroot->ms_ht, &op->g.oid); if (msp == NULL) errh_Bugcheck(*sts, "mount server inconsitency"); msp->msor = pool_cNRef; pool_Qremove(NULL, gdbroot->pool, &msp->nodms_ll); /* Todo !!! Clear alarm and blocklevel in all mount clients. */ } cvol_FlushObject(op); } pwr_Assert(vp->l.flags.b.inOwnList); pool_Qremove(NULL, gdbroot->pool, &vp->l.own_ll); vp->l.flags.b.inOwnList = 0; vp->g.nid = pwr_cNNodeId; pwr_Assert(pool_QisEmpty(NULL, gdbroot->pool, &vp->u.c.cacheLock.lh)); pwr_Assert(vp->u.c.cacheLock.lc == 0); pwr_Assert(pool_QisEmpty(NULL, gdbroot->pool, &vp->u.c.cacheVol.lh)); pwr_Assert(vp->u.c.cacheVol.lc == 0); vp->l.flags.b.isConnected = 0; vp->l.flags.b.isCached = 0; vp->l.flags.b.netCached = 0; vp->l.flags.b.remote = 0; }
void subs_DeleteServer ( sub_sServer *sp ) { pwr_tStatus sts; sub_sBuffer *bp; gdb_sObject *op; gdb_AssumeLocked; bp = pool_Address(NULL, gdbroot->pool, sp->br); /* Disconnect from buffer. If the number of servers connected to the buffer reaches zero, the buffer gets disposed when it times out the next time. */ pool_Qremove(NULL, gdbroot->pool, &sp->bufsubs_ll); bp->bufsubs_lc -= 1; bp->totsize -= sp->aref.Size; /* Now give the subsrv entry back to the pool. */ pool_Qremove(NULL, gdbroot->pool, &sp->subs_ll); gdbroot->db->subs_lc--; pool_Qremove(NULL, gdbroot->pool, &sp->nodsubs_ll); /* Remove from server table. */ hash_Remove(&sts, gdbroot->subs_ht, sp); /* Decrement subcounter for referenced object */ op = vol_OidToObject(&sts, sp->aref.Objid, gdb_mLo_owned, vol_mTrans_alias, cvol_eHint_none); if (op != NULL) { op->u.n.subcount--; } pool_Free(NULL, gdbroot->pool, sp); }
static void cancelTimeoutWatch ( sub_sClient *cp ) { gdb_AssumeLocked; if (cp->tmoactive) { pool_Qremove(NULL, gdbroot->pool, &cp->subt_ll); cp->tmoactive = FALSE; gdbroot->db->subt_lc--; } }
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); }
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; }
void dl_Cancel ( pwr_tStatus *sts, pwr_tDlid dlid ) { dl_sLink *dp; gdb_sObject *op; cdh_uRefId rid; gdb_AssumeLocked; rid.pwr = dlid; if (rid.r.vid_3 != cdh_eVid3_dlid) { pwr_Status(sts, GDH__DLID); return; } dp = hash_Search(sts, gdbroot->subc_ht, &dlid); if (dp == NULL) { pwr_Status(sts, GDH__DLID); return; } dp = hash_Remove(sts, gdbroot->subc_ht, dp); if (dp == NULL) errh_Bugcheck(GDH__WEIRD, "hash_Remove"); pool_Qremove(NULL, gdbroot->pool, &dp->dl_ll); gdbroot->db->dl_lc--; op = pool_Address(NULL, gdbroot->pool, dp->opr); if (op == NULL) errh_Bugcheck(GDH__WEIRD, "direct link inconsitency"); gdb_UnlockObject(sts, op); pool_Free(NULL, gdbroot->pool, dp); return; }
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; } }
static void deleteClient ( sub_sClient *cp ) { pwr_tStatus sts; gdb_sNode *np; gdb_AssumeLocked; cancelTimeoutWatch(cp); subc_RemoveFromMessage(cp); hash_Remove(&sts, gdbroot->subc_ht, cp); if (EVEN(sts)) errh_Bugcheck(sts, "remove client from hash table"); np = hash_Search(&sts, gdbroot->nid_ht, &cp->nid); if (np == NULL) errh_Bugcheck(sts, "node not found"); pool_Qremove(&sts, gdbroot->pool, &cp->subc_ll); np->subc_lc--; if (cp->userdata != pool_cNRef) { pool_FreeReference(NULL, gdbroot->rtdb, cp->userdata); } if (cp->cclass != pool_cNRef) { gdb_sCclass *ccp; ccp = pool_Address(NULL, gdbroot->pool, cp->cclass); if (ccp == NULL) errh_Bugcheck(GDH__WEIRD, "cached class address"); cmvolc_UnlockClass(NULL, ccp); cp->cclass = pool_cNRef; } pool_Free(NULL, gdbroot->pool, cp); }
void subc_RemoveFromMessage ( sub_sClient *cp ) { sub_sMessage *mp; if (cp->submsg == pool_cNRef) return; gdb_AssumeLocked; mp = pool_Address(NULL, gdbroot->pool, cp->submsg); if (--mp->msg.count == 0) { pool_Qremove(NULL, gdbroot->pool, &mp->subm_ll); gdbroot->db->subm_lc--; pool_Free(NULL, gdbroot->pool, mp); } /* Last reference to that SUBMSG, dispose it */ cp->submsg = pool_cNRef; cp->subdata = pool_cNRef; }
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 sancm_Remove ( pwr_tStatus *status, gdb_sNode *np ) { net_sSanRemove *rp; pool_sQlink *ol; gdb_sObject *op; int count; int i; qcom_sQid tgt; if (status != NULL) *status = 1; gdb_AssumeLocked; if (np->sancRem_lc == 0) return; count = MIN(np->sancRem_lc, net_cSanMaxRemove); rp = malloc(sizeof(net_sSanRemove) + (count - 1) * sizeof(rp->sid[0])); if (rp == NULL) return; tgt.nid = np->nid; tgt.qix = net_cProcHandler; for ( i = 0, ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancRem_lh); ol != &np->sancRem_lh; ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancRem_lh) ) { op = pool_Qitem(ol, gdb_sObject, u.c.sanc_ll); rp->sid[i] = op->u.c.sanid; i++; pwr_Assert(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((op->u.c.flags.m & gdb_mCo_inSancList) == 0); pwr_Assert(np->sancRem_lc != 0); np->sancRem_lc--; #if 0 cvolc_TrimObject(op); #endif if (i >= count) { rp->count = count; gdb_Unlock; net_Put(NULL, &tgt, rp, net_eMsg_sanRemove, 0, pwr_Offset(rp, sid[i]), 0); gdb_Lock; i = 0; } } pwr_Assert(np->sancRem_lc == 0); /* Send remaining san removes. */ if (i > 0) { rp->count = count; gdb_Unlock; net_Put(NULL, &tgt, rp, net_eMsg_sanRemove, 0, pwr_Offset(rp, sid[i]), 0); gdb_Lock; } free(rp); }
void sancm_FlushNode ( pwr_tStatus *status, gdb_sNode *np ) { pool_sQlink *ol; gdb_sObject *op; if (status != NULL) *status = 1; gdb_AssumeLocked; for ( 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); 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(np->sancAdd_lc == 0); for ( ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancAct_lh); ol != &np->sancAct_lh; ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancAct_lh) ) { op = pool_Qitem(ol, gdb_sObject, u.c.sanc_ll); pwr_Assert(op->u.c.flags.b.sancAct); 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--; } pwr_Assert(np->sancAct_lc == 0); for ( ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancRem_lh); ol != &np->sancRem_lh; ol = pool_Qsucc(NULL, gdbroot->pool, &np->sancRem_lh) ) { op = pool_Qitem(ol, gdb_sObject, u.c.sanc_ll); pwr_Assert(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((op->u.c.flags.m & gdb_mCo_inSancList) == 0); pwr_Assert(np->sancRem_lc != 0); np->sancRem_lc--; } pwr_Assert(np->sancRem_lc == 0); return; }
pwr_tUInt32 sansm_Update(gdb_sNode* np) { static net_sSanUpdate* up = NULL; static san_sServer** spl = NULL; int i; pwr_tStatus sts; pwr_tUInt32 gen; pool_sQlink* sl; san_sServer* sp; qcom_sQid tgt; gdb_AssumeLocked; if (pool_QisEmpty(NULL, gdbroot->pool, &np->sansUpd_lh)) return 0; if (up == NULL) { up = malloc(sizeof(*up) + (net_cSanMaxUpdate - 1) * sizeof(up->data[0])); spl = malloc(sizeof(san_sServer*) * net_cSanMaxUpdate); } for (i = 0, sl = pool_Qsucc(NULL, gdbroot->pool, &np->sansUpd_lh); sl != &np->sansUpd_lh && i < net_cSanMaxUpdate; i++) { sp = pool_Qitem(sl, san_sServer, sansUpd_ll); sl = pool_Qsucc(NULL, gdbroot->pool, sl); pwr_Assert(sp->flags.b.sansUpd); up->data[i].al = sp->al; up->data[i].sane = sp->sane; spl[i] = sp; } up->count = i; tgt.nid = np->nid; tgt.qix = net_cProcHandler; gen = np->sans_gen; gdb_Unlock; net_Put(&sts, &tgt, up, net_eMsg_sanUpdate, 0, pwr_Offset(up, data[i]), 0); gdb_Lock; if (EVEN(sts)) return 0; if (gen == np->sans_gen) { for (i = 0; i < up->count; i++) { sp = spl[i]; pwr_Assert(sp->flags.b.sansUpd); pool_Qremove(NULL, gdbroot->pool, &sp->sansUpd_ll); sp->flags.b.sansUpd = 0; } } else { for (i = 0; i < up->count; i++) { sp = hash_Search(NULL, gdbroot->sans_ht, &up->data[i].sane.sid); if (sp != NULL) { pwr_Assert(sp->flags.b.sansUpd); pool_Qremove(NULL, gdbroot->pool, &sp->sansUpd_ll); sp->flags.b.sansUpd = 0; } } } return up->count; }
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 }