void cvolsm_GetObjectInfo ( qcom_sGet *get ) { pwr_tStatus sts; mvol_sAttribute Attribute; mvol_sAttribute *ap; int size; net_sGetObjectInfoR *rmp; void *p = NULL; net_sGetObjectInfo *mp = get->data; qcom_sPut put; gdb_sNode *np; cdh_uTypeId cid; gdb_sClass *cp; gdb_AssumeUnlocked; size = mp->aref.Size + sizeof(net_sGetObjectInfoR) - sizeof(rmp->info); size = (size + 3) & ~3; /* Size up to nearest multiple of 4. */ rmp = net_Alloc(&sts, &put, size, net_eMsg_getObjectInfoR); if (EVEN(sts)) return; gdb_ScopeLock { np = hash_Search(NULL, gdbroot->nid_ht, &get->sender.nid); pwr_Assert(np != NULL); memset( &Attribute, 0, sizeof(Attribute)); ap = vol_ArefToAttribute(&sts, &Attribute, &mp->aref, gdb_mLo_owned, vol_mTrans_alias); if (ap == NULL || ap->op == NULL) break; p = vol_AttributeToAddress(&sts, ap); } gdb_ScopeUnlock; if (p != NULL) { size = mp->aref.Size; cid.pwr = mp->aref.Body; cid.c.bix = 0; /* To get the class id. */ cp = hash_Search(&sts, gdbroot->cid_ht, &cid.pwr); if (cp != NULL) ndc_ConvertData(&sts, np, cp, &mp->aref, rmp->info, p, (pwr_tUInt32 *)&size, ndc_eOp_encode, mp->aref.Offset, 0); } rmp->aref = mp->aref; rmp->sts = sts; rmp->size = mp->aref.Size; net_Reply(&sts, get, &put, 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); } }