void subc_SetOld ( sub_sClient *cp ) { void *adrs; cp->old = TRUE; if (cp->userdata != pool_cNRef) { adrs = pool_Address(NULL, gdbroot->rtdb, cp->userdata); if (adrs != NULL) { memset(adrs, 0, cp->usersize); } } subc_RemoveFromMessage(cp); }
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 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); } }