// remove cycles void cleanUpGroupingRec(UINT address, ParentRefMap& parentMap, ChildRefMap& childMap, MapAddressToAllocation& addressesToAllocations, AddressSet& visited) { if (visited.find(address) != visited.end()) return; visited.insert(address); auto myUid = addressesToAllocations[address].uid; auto parents = parentMap[address]; // copy for (auto parent : parents) { auto parentUid = addressesToAllocations[parent].uid; bool eraseParent = (parentUid > myUid) || (address == parent); // remove self references if (eraseParent) { parentMap[address].erase(parent); childMap[parent].erase(address); } else { cleanUpGroupingRec(parent, parentMap, childMap, addressesToAllocations, visited); } } }
void checkMemoryGrouping(const MemoryTracker::TrackedAllocation& ta, AddressSet& addresses, ParentRefMap& parentMap, ChildRefMap& childMap) { //UINT * memory = (UINT*)address, *endMemory = (UINT*)(address+size); //use memory hacks to see if there's pointers to the allocations in here UINT * buf = new UINT[ta.bytes]; ZeroMemory(buf, ta.bytes); SIZE_T numberOfBytesRead = 0; if (ReadProcessMemory(global::hProcess, ta.mem, buf, ta.bytes, &numberOfBytesRead)) { UINT * memory = buf; UINT * endMemory = buf + (ta.bytes / sizeof(UINT)); // min( (ta.bytes / sizeof(UINT)), (numberOfBytesRead / sizeof(UINT)) ); for (; memory < endMemory; memory++) { auto it = addresses.find(*memory); if (it != addresses.end()) { parentMap[*it].insert((UINT)ta.mem); childMap[(UINT)ta.mem].insert(*it); } } } delete[] buf; }
AddressSet AddressDb::list() const { std::lock_guard<std::mutex> lock(mutex_); AddressSet out; for (const auto &i: addresses_) out.insert(i.first); return out; }
void printSingleAggregateGrouping(std::ostream& out, int level, UINT address, TrackedCallstack::ptr callstackPtr, ReferenceCount& rc, MapAddressToAllocation& addressToAllocationMap, ChildRefMap& childMap, AddressSet visited, UINT sumResponsible) { if (visited.find(address) != visited.end()) return; visited.insert(address); auto& alloc = addressToAllocationMap[address]; auto p = callstackPtr; indent(out, level) << "Allocations " << dec << rc.totalSize << " total bytes for " << rc.instances << " instances; Responsible for " << sumResponsible << " nested bytes. Callstack:" << endl; for (auto s: p->callstackVerbose) { indent(out, level) << "|" << s << endl; } printAggregateGroupings(out, level + 1, childMap[address], addressToAllocationMap, childMap, visited); }
UINT findResponsibleBytes(UINT address, MapAddressToAllocation& addressToAllocationMap, ChildRefMap& childMap, AddressSet& visitedInThisSearch) { if (visitedInThisSearch.find(address) != visitedInThisSearch.end()) return 0; visitedInThisSearch.insert(address); UINT sum = 0; sum += addressToAllocationMap[address].bytes; for (UINT c: childMap[address]) { sum += findResponsibleBytes(c, addressToAllocationMap, childMap, visitedInThisSearch); } return sum; }
void MemoryTracker::ReportGroupLeaks(std::ostream& out, bool intensive, bool aggregate) { AddressSet allAddresses; MapAddressToAllocation addressesToAllocations; for (auto& a: trackedAllocations) //get all addresses { allAddresses.insert((UINT)a.mem); addressesToAllocations[(UINT)a.mem] = a; } //Find the groupings. ParentRefMap parentMap; ChildRefMap childMap; for (auto& a: trackedAllocations) { checkMemoryGrouping(a, allAddresses, parentMap, childMap); } //// clean up cycles //for (auto& a: trackedAllocations) // cleanUpGroupingRec((UINT)a.mem, parentMap, childMap, addressesToAllocations, AddressSet()); cleanUpAllGroupings(trackedAllocations, parentMap, childMap, addressesToAllocations); //find all the root addresses - recursive AddressSet rootAddresses; { AddressSet visited; for (auto& a: trackedAllocations) { walkUpGrouping((UINT)a.mem, parentMap, rootAddresses, visited); } } AddressSet visited; if (aggregate) { printAggregateGroupings(out, 0, rootAddresses, addressesToAllocations, childMap, visited); } else { for (UINT a: rootAddresses) { printGroupings(out, 0, a, addressesToAllocations, childMap, visited); } } }
void printGroupings(std::ostream& out, int level, UINT address, MapAddressToAllocation& addressToAllocationMap, ChildRefMap& childMap, AddressSet& visited) { if (visited.find(address) != visited.end()) return; visited.insert(address); auto& alloc = addressToAllocationMap[address]; auto p = alloc.callStack; indent(out, level) << "Allocation at " << hex << address << " " << dec << alloc.bytes << " bytes; Callstack:" << endl; for (auto s: p->callstackVerbose) { indent(out, level) << s << endl; } for (auto a: childMap[address]) { printGroupings(out, level + 1, a, addressToAllocationMap, childMap, visited); } }
//recursive void walkUpGrouping(UINT address, ParentRefMap& parentMap, AddressSet& outAddresses, AddressSet& visited) { visited.insert(address); if (parentMap[address].size() == 0) //base case { outAddresses.insert(address); } else { for (UINT a: parentMap[address]) { if (visited.find(a) == visited.end()) { walkUpGrouping(a, parentMap, outAddresses, visited); } } } }
void SubnetTopology::getRemovedDevices(AddressSet& addressSet) { markReachableNodes(MANAGER_ADDRESS, setNextSearchId()); for (NodeMap::iterator itNode = nodes.begin(); itNode != nodes.end(); ++itNode) { if (itNode->second.getSearchId() != searchId) { addressSet.insert(itNode->first); } } }
static ir::PTXU64 extent(const executive::ExecutableKernel& kernel) { typedef std::unordered_set<ir::PTXU64> AddressSet; report("Computing extent for kernel " << kernel.name); AddressSet encountered; AddressSet pointers; ir::PTXU64 extent = kernel.constMemorySize() + kernel.parameterMemorySize() + kernel.totalSharedMemorySize() + kernel.localMemorySize(); executive::ExecutableKernel::TextureVector textures = kernel.textureReferences(); for (executive::ExecutableKernel::TextureVector::iterator texture = textures.begin(); texture != textures.end(); ++texture) { report(" Checking texture mapped address " << (*texture)->data); pointers.insert((ir::PTXU64)(*texture)->data); } #if 0 for (ir::Kernel::ParameterVector::const_iterator parameter = kernel.parameters.begin(); parameter != kernel.parameters.end(); ++parameter) { ir::PTXU64 address = 0; for (ir::Parameter::ValueVector::const_iterator element = parameter->arrayValues.begin(); element != parameter->arrayValues.end(); ++element) { switch (parameter->type) { case ir::PTXOperand::b8: case ir::PTXOperand::s8: case ir::PTXOperand::u8: { address <<= 8; address |= element->val_u8; break; } case ir::PTXOperand::b16: case ir::PTXOperand::s16: case ir::PTXOperand::u16: { address <<= 16; address |= element->val_u16; break; } case ir::PTXOperand::b32: case ir::PTXOperand::s32: case ir::PTXOperand::u32: { address <<= 32; address |= element->val_u32; break; } case ir::PTXOperand::b64: case ir::PTXOperand::s64: case ir::PTXOperand::u64: { address = element->val_u64; break; } default: break; } report(" Checking address " << (void*)address); pointers.insert(address); } } #endif for(AddressSet::iterator pointer = pointers.begin(); pointer != pointers.end(); ++pointer) { executive::Device::MemoryAllocation* allocation = kernel.device->getMemoryAllocation((void*)*pointer); if(allocation != 0) { if(encountered.insert((ir::PTXU64)allocation->pointer()).second) { extent += allocation->size(); } } } return extent; }
static Status bridgeDoSweep(Wallet &wallet, PendingSweep &sweep, tABC_BitCoin_Event_Callback fAsyncCallback, void *pData) { // Find utxos for this address: AddressSet addresses; addresses.insert(sweep.address); auto utxos = wallet.txCache.get_utxos(addresses); // Bail out if there are no funds to sweep: if (!utxos.size()) { // Tell the GUI if there were funds in the past: if (wallet.txCache.has_history(sweep.address)) { ABC_DebugLog("IncomingSweep callback: wallet %s, value: 0", wallet.id().c_str()); tABC_AsyncBitCoinInfo info; info.pData = pData; info.eventType = ABC_AsyncEventType_IncomingSweep; Status().toError(info.status, ABC_HERE()); info.szWalletUUID = wallet.id().c_str(); info.szTxID = nullptr; info.sweepSatoshi = 0; fAsyncCallback(&info); sweep.done = true; } return Status(); } // Build a transaction: bc::transaction_type tx; tx.version = 1; tx.locktime = 0; // Set up the output: Address address; wallet.addresses.getNew(address); bc::transaction_output_type output; ABC_CHECK(outputScriptForAddress(output.script, address.address)); tx.outputs.push_back(output); // Set up the inputs: uint64_t fee, funds; ABC_CHECK(inputsPickMaximum(fee, funds, tx, utxos)); if (outputIsDust(funds)) return ABC_ERROR(ABC_CC_InsufficientFunds, "Not enough funds"); tx.outputs[0].value = funds; // Now sign that: KeyTable keys; keys[sweep.address] = sweep.key; ABC_CHECK(signTx(tx, wallet.txCache, keys)); // Send: bc::data_chunk raw_tx(satoshi_raw_size(tx)); bc::satoshi_save(tx, raw_tx.begin()); ABC_CHECK(broadcastTx(wallet, raw_tx)); // Calculate transaction information: const auto info = wallet.txCache.txInfo(tx, wallet.addresses.list()); // Save the transaction metadata: Tx meta; meta.ntxid = info.ntxid; meta.txid = info.txid; meta.timeCreation = time(nullptr); meta.internal = true; meta.metadata.amountSatoshi = funds; meta.metadata.amountFeesAirbitzSatoshi = 0; ABC_CHECK(gContext->exchangeCache.satoshiToCurrency( meta.metadata.amountCurrency, info.balance, static_cast<Currency>(wallet.currency()))); ABC_CHECK(wallet.txs.save(meta)); // Update the transaction cache: if (wallet.txCache.insert(tx)) watcherSave(wallet).log(); // Failure is not fatal wallet.balanceDirty(); ABC_CHECK(wallet.addresses.markOutputs(info.ios)); // Done: ABC_DebugLog("IncomingSweep callback: wallet %s, txid: %s, value: %d", wallet.id().c_str(), info.txid.c_str(), output.value); tABC_AsyncBitCoinInfo async; async.pData = pData; async.eventType = ABC_AsyncEventType_IncomingSweep; Status().toError(async.status, ABC_HERE()); async.szWalletUUID = wallet.id().c_str(); async.szTxID = info.txid.c_str(); async.sweepSatoshi = output.value; fAsyncCallback(&async); sweep.done = true; return Status(); }
bool SubnetTopology::releaseRemoved(EngineOperations& engineOperations, AddressSet& addressSet) { bool isGood = false; bool repeat = false; SubnetTdma& subnetTdma = NetworkEngine::instance().getSubnetTdma(); SubnetServices& subnetServices = NetworkEngine::instance().getSubnetServices(); DevicesTable& devicesTable = NetworkEngine::instance().getDevicesTable(); markReachableNodes(MANAGER_ADDRESS, setNextSearchId()); // steps through every node and see if the node has been touched (node.searchId has the value of // the current searchId) std::set<Uint16> affectedGraphs; for (NodeMap::iterator itNode = nodes.begin(); itNode != nodes.end(); ++itNode) { if (itNode->second.getSearchId() != searchId || itNode->second.getStatus() == Status::CANDIDATE_FOR_REMOVAL ) { LOG_INFO("Delete Node: " << ToStr(itNode->second.getNodeAddress())); affectedGraphs.insert( itNode->second.getOutboundGraphId() ); affectedGraphs.insert( itNode->second.getInboundGraphId() ); itNode->second.setStatus(Status::REMOVED); { Device& device = devicesTable.getDevice(itNode->first); if (device.capabilities.isGateway()) { device.deviceRequested832 = true; } else { device.deviceRequested832 = false; } // notify GW about the device has been removed (if the GW is not deleted also) if (devicesTable.existsDevice(GATEWAY_ADDRESS)) { IEngineOperationPointer operation(new ChangeNotificationOperation((uint32_t) GATEWAY_ADDRESS, device.address64, 769)); operation->setDependency(WaveDependency::TENTH); engineOperations.addOperation(operation); } } subnetTdma.setRemovedStatus(itNode->first); subnetServices.setRemovedStatus(itNode->first); devicesTable.setRemoveStatus(itNode->first); EdgeList& edges = itNode->second.getOutBoundEdges(); for (EdgeList::iterator itEdge = edges.begin(); itEdge != edges.end(); ++itEdge) { if (itEdge->getStatus() == Status::DELETED) { continue; } GraphNeighborMap& neighbors = itEdge->getGraphs(); for (GraphNeighborMap::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { if (it->second.status == Status::DELETED) { continue; } if (!existsPath(it->first)) { //TODO: ivp - !!! workaround it->second.status = Status::DELETED; LOG_ERROR("Deleted graph: " << ToStr(it->first) << " exists on node: " << itNode->second); } else { affectedGraphs.insert(it->first); LOG_INFO("Affected graph(1): " << ToStr(it->first)); } } } } else { EdgeList& edges = itNode->second.getOutBoundEdges(); for (EdgeList::iterator itEdge = edges.begin(); itEdge != edges.end();) { if (itEdge->getStatus() == Status::DELETED) { ++itEdge; continue; } //if peer node is not found mark the edge as deleted NodeMap::iterator it_peerNode = nodes.find(itEdge->getDestination()); if (it_peerNode == nodes.end()) { LOG_DEBUG("Mark deleted edge: its peer is down."); itEdge->setStatus(Status::DELETED); ++itEdge; continue; } Node& peerNode = it_peerNode->second; //Node& peerNode = getNode(itEdge->getDestination()); if (peerNode.getSearchId() != searchId) { bool hasGraphNeighbors = false; //generate delete GraphNeighbor operation GraphNeighborMap& neighbors = itEdge->getGraphs(); for (GraphNeighborMap::iterator it = neighbors.begin(); it != neighbors.end(); ++it) { if (it->second.status == Status::DELETED) { continue; } if (!existsPath(it->first)) { //TODO: ivp - !!! workaround it->second.status = Status::DELETED; LOG_ERROR("Deleted graph: " << ToStr(it->first) << " exists on node: " << itNode->second); } else { affectedGraphs.insert(it->first); LOG_INFO("Affected graph(2 ): " << ToStr(it->first)); } hasGraphNeighbors = true; it->second.status = Status::DELETED; if (it->first == OUTBOUND_GW_GRAPH_ID // && itEdge->getSource() == MANAGER_ADDRESS // && itEdge->getDestination() == GATEWAY_ADDRESS) { continue; } IEngineOperationPointer operation(new NeighborGraphRemovedOperation(itEdge->getSource(), it->first, itEdge->getDestination())); operation->setDependency(WaveDependency::NINETH); engineOperations.addOperation(operation); } if (hasGraphNeighbors) { LOG_DEBUG("releaseRemoved - set DELETED edge " << *itEdge); itEdge->setStatus(Status::DELETED); if ((itNode->second.getNodeType() == NodeType::NODE) && (itNode->second.getSecondaryClkSource() == peerNode.getNodeAddress())) { itNode->second.resetSecondaryClkSource(); SetClockSourceOperation *op = new SetClockSourceOperation(itNode->second.getNodeAddress(), peerNode.getNodeAddress(), 0); IEngineOperationPointer engineOp(op); engineOp->setDependency(WaveDependency::SECOND); engineOperations.addOperation(engineOp); } itEdge++; } else { LOG_DEBUG("releaseRemoved - delete edge" << *itEdge); if ((itNode->second.getNodeType() == NodeType::NODE) && (itNode->second.getSecondaryClkSource() == peerNode.getNodeAddress())) { itNode->second.resetSecondaryClkSource(); SetClockSourceOperation *op = new SetClockSourceOperation(itNode->second.getNodeAddress(), peerNode.getNodeAddress(), 0); IEngineOperationPointer engineOp(op); engineOp->setDependency(WaveDependency::SECOND); engineOperations.addOperation(engineOp); } //edges.erase(itEdge++); itNode->second.removeEdge(itEdge); } } else { ++itEdge; } } } } // checks the affected routing graphs //if the source or destination of the graph is deleted, check if the graph is used by other route, //delete or change the source/destination of the graph for (std::set<Uint16>::iterator it = affectedGraphs.begin(); it != affectedGraphs.end(); ++it) { Path& path = getPath(*it); if (path.getType() == RoutingTypes::SOURCE_ROUTING) { isGood = path.checkSourcePath(); } else if (path.getType() == RoutingTypes::GRAPH_ROUTING || path.getType() == RoutingTypes::GRAPH_ROUTING_WITH_MIN_PATH_SELECTION) { isGood = path.checkGraphPath(engineOperations, setNextSearchId()); } LOG_DEBUG("releaseRemoved - isGood=" << (int) isGood << " path: " << path); //TODO: temporary until a graph is used by multiple devices - in the case // that a graph is used by multiple routes, update the source/destination of the graph if (!isGood) { Address32 address = path.getSource(); if (address == MANAGER_ADDRESS) { address = path.getDestination(); } NodeMap::iterator nodeIt = nodes.find(address); if (nodeIt != nodes.end()) { if (nodeIt->second.getStatus() != Status::REMOVED) { nodeIt->second.setStatus(Status::CANDIDATE_FOR_REMOVAL); repeat = true; } } if (nodeIt == nodes.end() || nodeIt->second.getStatus() == Status::REMOVED) { LOG_DEBUG("releaseRemoved - delete path: " << path); PathMap::iterator itPath = paths.find(*it); if (itPath != paths.end()) { //paths.erase(itPath); deletePath(itPath); } } } else { graphsToRefresh.insert(std::pair<int, Uint16>(engineOperations.getOperationsSetIndex(), *it)); PathMap::iterator itPath = paths.find(*it); if (itPath != paths.end()) { itPath->second.createTopologicalOrder(); } } } for (PathMap::iterator it = paths.begin(); it != paths.end();) { if (it->second.getEvaluatePathPriority() != EvaluatePathPriority::InboundAttach && it->second.getEvaluatePathPriority() != EvaluatePathPriority::OutboundAttach && devicesTable.getDeviceStatus(it->second.getSource()) != DeviceStatus::DELETED && devicesTable.getDeviceStatus(it->second.getDestination()) != DeviceStatus::DELETED ) { ++it; continue; } Address32 address = it->second.getSource(); if (address == MANAGER_ADDRESS || address == GATEWAY_ADDRESS) { address = it->second.getDestination(); } NodeMap::iterator itNode = nodes.find(address); if (itNode == nodes.end() || itNode->second.getStatus() == Status::REMOVED) { //paths.erase(it++); deletePath(it); } else { ++it; } } for (NodeMap::iterator it = nodes.begin(); it != nodes.end();) { if (it->second.getStatus() == Status::REMOVED) { subnetServices.setRemovedStatus(it->first); subnetTdma.setRemovedStatus(it->first); devicesTable.setRemoveStatus(it->first); addressSet.insert(it->first); if ((it->second.getNodeType() == NodeType::NODE) // && (it->second.hasNeighbor(it->second.getBackboneAddress())) // && (devicesTable.existsDevice(it->second.getBackboneAddress()))) { SetClockSourceOperation *op = new SetClockSourceOperation(it->second.getBackboneAddress(), it->first, 0x2); IEngineOperationPointer engineOp(op); engineOp->setDependency(WaveDependency::FIFTH); engineOperations.addOperation(engineOp); } nodes.erase(it++); } else { ++it; } } if (repeat) { LOG_DEBUG("Repeat"); } return repeat; }