public override bool getBlocks(List <Hash> blockHashes, List <BlockDetails> blocks) { if (state.load() != State.INITIALIZED) { throw std::system_error(GlobalMembers.make_error_code(CryptoNote.error.BlockchainExplorerErrorCodes.NOT_INITIALIZED)); } if (blockHashes.Count == 0) { return(true); } logger.functorMethod(DEBUGGING) << "Get blocks by hash request came."; NodeRequest new request((INodeOriginal.Callback cb) => { node.getBlocks(blockHashes, blocks, cb); }); std::error_code ec = request.performBlocking(); if (ec != null) { logger.functorMethod(ERROR) << "Can't get blocks by hash: " << ec.message(); throw std::system_error(ec); } Debug.Assert(blocks.Count == blockHashes.Count); return(true); }
//C++ TO C# CONVERTER TODO TASK: The original C++ template specifier was replaced with a C# generic specifier, which may not produce the same behavior: //ORIGINAL LINE: template <typename RequestType, typename ResponseType, typename RequestHandler> private HandlerFunction jsonHandler <RequestType, ResponseType, RequestHandler>(RequestHandler handler) { //C++ TO C# CONVERTER TODO TASK: Only lambda expressions having all locals passed by reference can be converted to C#: //ORIGINAL LINE: return [handler, this] (const Common::JsonValue& jsonRpcParams, Common::JsonValue& jsonResponse) mutable return((Common.JsonValue jsonRpcParams.functorMethod, Common.JsonValue jsonResponse.functorMethod) => mutable { RequestType request = new default(RequestType); ResponseType response = new default(ResponseType); try { //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'const_cast' in C#: CryptoNote.JsonInputValueSerializer inputSerializer = new CryptoNote.JsonInputValueSerializer(const_cast <Common.JsonValue&>(jsonRpcParams.functorMethod)); SerializeRequest(request, inputSerializer.functorMethod); } catch (System.Exception) { makeGenericErrorReponse(jsonResponse.functorMethod, "Invalid Request", -32600); return; } std::error_code ec = handler(request, response); if (ec != null) { makeErrorResponse(ec, jsonResponse.functorMethod); return; } CryptoNote.JsonOutputStreamSerializer outputSerializer = new CryptoNote.JsonOutputStreamSerializer(); CryptoNote.GlobalMembers.serialize(response, outputSerializer.functorMethod); fillJsonResponse(outputSerializer.getValue.functorMethod(), jsonResponse.functorMethod); });
public override bool isSynchronized() { if (state.load() != State.INITIALIZED) { throw std::system_error(GlobalMembers.make_error_code(CryptoNote.error.BlockchainExplorerErrorCodes.NOT_INITIALIZED)); } logger.functorMethod(DEBUGGING) << "Synchronization status request came."; bool syncStatus = false; NodeRequest new request((INodeOriginal.Callback cb) => { node.isSynchronized(ref syncStatus, cb); }); std::error_code ec = request.performBlocking(); if (ec != null) { logger.functorMethod(ERROR) << "Can't get synchronization status: " << ec.message(); throw std::system_error(ec); } synchronized.store(syncStatus); return(syncStatus); }
public void onError(std::error_code ec, uint height) { if (height != GlobalMembers.WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { transfers.detach(height); } m_observerManager.notify(ITransfersObserver.onError, this, height, ec); }
public void rename(string newPath, std::error_code ec) { m_file.rename(newPath, ec); if (ec == null) { m_path = newPath; } }
public void close(std::error_code ec) { m_file.close(ec); if (ec == null) { m_prefixSize = 0; m_suffixSize = 0; m_path = ""; } }
public void close() { std::error_code ec = new std::error_code(); close(ec); if (ec != null) { throw std::system_error(ec, "FileMappedVector::close"); } }
public void waitForInitEnd() { std::error_code ec = initFuture.get(); if (ec != null) { throw std::system_error(ec); } return; }
public void open(string path) { std::error_code ec = new std::error_code(); open(path, ref ec); if (ec != null) { throw std::system_error(ec, "MemoryMappedFile::open"); } }
public void close() { std::error_code ec = new std::error_code(); close(ref ec); if (ec != null) { throw std::system_error(ec, "MemoryMappedFile::close"); } }
public void create(string path, uint64_t size, bool overwrite) { std::error_code ec = new std::error_code(); create(path, new uint64_t(size), overwrite, ref ec); if (ec != null) { throw std::system_error(ec, "MemoryMappedFile::create"); } }
private std::error_code preprocessOutputs(TransactionBlockInfo blockInfo, ITransactionReader tx, PreprocessInfo info) { Dictionary <PublicKey, List <uint> > outputs = new Dictionary <PublicKey, List <uint> >(); try { GlobalMembers.findMyOutputs(tx, m_viewSecret, m_spendKeys, outputs); } catch (System.Exception e) { m_logger.functorMethod(WARNING, BRIGHT_RED) << "Failed to process transaction: " << e.Message << ", transaction hash " << Common.GlobalMembers.podToHex(tx.GetTransactionHash()); return(std::error_code()); } if (outputs.Count == 0) { return(std::error_code()); } std::error_code errorCode = new std::error_code(); var txHash = tx.GetTransactionHash(); if (blockInfo.height != GlobalMembers.WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: errorCode = getGlobalIndices(reinterpret_cast<const Hash&>(txHash), info.globalIdxs); errorCode.CopyFrom(getGlobalIndices(reinterpret_cast <const Hash&>(txHash), info.globalIdxs)); if (errorCode != null) { return(errorCode); } } foreach (var kv in outputs) { var it = m_subscriptions.find(kv.first); //C++ TO C# CONVERTER TODO TASK: Iterators are only converted within the context of 'while' and 'for' loops: if (it != m_subscriptions.end()) { auto transfers = info.outputs[kv.first]; //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: errorCode = createTransfers(it->second->getKeys(), blockInfo, tx, kv.second, info.globalIdxs, transfers, m_logger); //C++ TO C# CONVERTER TODO TASK: Iterators are only converted within the context of 'while' and 'for' loops: errorCode.CopyFrom(CryptoNote.GlobalMembers.createTransfers(it.second.getKeys(), blockInfo, tx, kv.second, info.globalIdxs, transfers, m_logger.functorMethod)); if (errorCode != null) { return(errorCode); } } } return(std::error_code()); }
public void flush(uint8_t data, uint64_t size) { Debug.Assert(isOpened()); std::error_code ec = new std::error_code(); flush(data, new uint64_t(size), ref ec); if (ec != null) { throw std::system_error(ec, "MemoryMappedFile::flush"); } }
public void rename(string newPath) { Debug.Assert(isOpened()); std::error_code ec = new std::error_code(); rename(newPath, ref ec); if (ec != null) { throw std::system_error(ec, "MemoryMappedFile::rename"); } }
public void open(string path, ref std::error_code ec) { if (isOpened()) { close(ref ec); if (ec != null) { return; } } //C++ TO C# CONVERTER TODO TASK: Only lambda expressions having all locals passed by reference can be converted to C#: //ORIGINAL LINE: Tools::ScopeExit failExitHandler([this, &ec] Tools.ScopeExit failExitHandler(() => { ec = std::error_code(errno, std::system_category()); std::error_code ignore = new std::error_code(); close(ref ignore); }); m_file = global::open(path, O_RDWR, S_IRUSR | S_IWUSR); if (m_file == -1) { return; } stat fileStat = new stat(); int result = global::fstat(m_file, fileStat); if (result == -1) { return; } //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: m_size = static_cast<uint64_t>(fileStat.st_size); m_size.CopyFrom((uint64_t)fileStat.st_size); //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: m_data = reinterpret_cast <uint8_t>(global::mmap(null, (size_t)m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_file, 0)); if (m_data == MAP_FAILED) { return; } m_path = path; ec = std::error_code(); failExitHandler.cancel(); }
//C++ TO C# CONVERTER TODO TASK: The original C++ template specifier was replaced with a C# generic specifier, which may not produce the same behavior: //ORIGINAL LINE: template<class F> //C++ TO C# CONVERTER TODO TASK: 'rvalue references' have no equivalent in C#: private void atomicUpdate0 <F>(ulong newCapacity, ulong newPrefixSize, ulong newSuffixSize, F&& func) { if (m_file.path() != m_path) { throw new System.Exception("Vector is mapped to a .bak file due to earlier errors"); } boost::filesystem.path bakPath = m_path + ".bak"; boost::filesystem.path tmpPath = boost::filesystem.unique_path(m_path + ".tmp.%%%%-%%%%"); if (boost::filesystem.exists(bakPath)) { boost::filesystem.remove(bakPath); } Tools.ScopeExit tmpFileDeleter(() => { boost::system.error_code ignore = new boost::system.error_code(); boost::filesystem.remove(tmpPath, ignore); }); // Copy file. It is slow but atomic operation FileMappedVector <T> tmpVector = new FileMappedVector <T>(); tmpVector.create(tmpPath.string(), new ulong(newCapacity), new ulong(newPrefixSize), new ulong(newSuffixSize)); func(tmpVector); tmpVector.flush(); // Swap files std::error_code ec = new std::error_code(); std::error_code ignore = new std::error_code(); m_file.rename(bakPath.string()); tmpVector.rename(m_path, ec); if (ec != null) { // Try to restore and ignore errors m_file.rename(m_path, ignore); throw std::system_error(ec, "Failed to swap temporary and vector files"); } m_path = bakPath.string(); swap(tmpVector); tmpFileDeleter.cancel(); // Remove .bak file and ignore errors tmpVector.close(ignore); boost::system.error_code boostError = new boost::system.error_code(); boost::filesystem.remove(bakPath, boostError); }
public void rename(string newPath, ref std::error_code ec) { Debug.Assert(isOpened()); int result = global::rename(m_path, newPath); if (result == 0) { m_path = newPath; ec = std::error_code(); } else { ec = std::error_code(errno, std::system_category()); } }
public override std::error_code onPoolUpdated(List <std::unique_ptr <ITransactionReader> > addedTransactions, List <Hash> deletedTransactions) { TransactionBlockInfo unconfirmedBlockInfo = new TransactionBlockInfo(); unconfirmedBlockInfo.timestamp = 0; unconfirmedBlockInfo.height = GlobalMembers.WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; std::error_code processingError = new std::error_code(); foreach (var cryptonoteTransaction in addedTransactions) { m_poolTxs.emplace(cryptonoteTransaction.getTransactionHash()); //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: processingError = processTransaction(unconfirmedBlockInfo, *cryptonoteTransaction.get()); processingError.CopyFrom(processTransaction(unconfirmedBlockInfo, *cryptonoteTransaction.get())); if (processingError != null) { foreach (var sub in m_subscriptions) { sub.second.onError(processingError, GlobalMembers.WALLET_UNCONFIRMED_TRANSACTION_HEIGHT); } return(processingError); } } foreach (var deletedTxHash in deletedTransactions) { m_poolTxs.erase(deletedTxHash); m_observerManager.notify(IBlockchainConsumerObserver.onTransactionDeleteBegin, this, deletedTxHash); foreach (var sub in m_subscriptions) { //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: sub.second.deleteUnconfirmedTransaction(*reinterpret_cast <const Hash>(deletedTxHash)); } m_observerManager.notify(IBlockchainConsumerObserver.onTransactionDeleteEnd, this, deletedTxHash); } return(std::error_code()); }
public void close(ref std::error_code ec) { int result; if (m_data != null) { flush(m_data, new uint64_t(m_size), ref ec); if (ec != null) { return; } result = global::munmap(m_data, (size_t)m_size); if (result == 0) { m_data = null; } else { ec = std::error_code(errno, std::system_category()); return; } } if (m_file != -1) { result = global::close(m_file); if (result == 0) { m_file = -1; ec = std::error_code(); } else { ec = std::error_code(errno, std::system_category()); return; } } ec = std::error_code(); }
public override bool getPoolState(List <Hash> knownPoolTransactionHashes, Hash knownBlockchainTopHash, ref bool isBlockchainActual, List <TransactionDetails> newTransactions, List <Hash> removedTransactions) { if (state.load() != State.INITIALIZED) { throw std::system_error(GlobalMembers.make_error_code(CryptoNote.error.BlockchainExplorerErrorCodes.NOT_INITIALIZED)); } logger.functorMethod(DEBUGGING) << "Get pool state request came."; List <std::unique_ptr <ITransactionReader> > rawNewTransactions = new List <std::unique_ptr <ITransactionReader> >(); NodeRequest new request((INodeOriginal.Callback callback) => { List <Hash> hashes = new List <Hash>(); foreach (Hash hash in knownPoolTransactionHashes) { hashes.Add(std::move(hash)); } node.getPoolSymmetricDifference(std::move(hashes), reinterpret_cast <Hash&>(knownBlockchainTopHash), ref isBlockchainActual, rawNewTransactions, removedTransactions, callback); }); std::error_code ec = request.performBlocking(); if (ec != null) { logger.functorMethod(ERROR) << "Can't get pool state: " << ec.message(); throw std::system_error(ec); } List <Hash> newTransactionsHashes = new List <Hash>(); foreach (var rawTransaction in rawNewTransactions) { Hash transactionHash = rawTransaction.getTransactionHash(); newTransactionsHashes.Add(std::move(transactionHash)); } return(getTransactions(newTransactionsHashes, newTransactions)); }
public override std::error_code read(IReadBatch batch) { if (state.load() != State.INITIALIZED) { throw new System.Exception("Not initialized."); } rocksdb.ReadOptions readOptions = new rocksdb.ReadOptions(); List <string> rawKeys = new List <string>(batch.getRawKeys()); List <rocksdb.Slice> keySlices = new List <rocksdb.Slice>(); keySlices.Capacity = rawKeys.Count; foreach (string key in rawKeys) { keySlices.emplace_back(new rocksdb.Slice(key)); } List <string> values = new List <string>(); values.Capacity = rawKeys.Count; List <rocksdb.Status> statuses = db.MultiGet(readOptions, keySlices, values); std::error_code error = new std::error_code(); List <bool> resultStates = new List <bool>(); foreach (rocksdb in :Status & status : statuses) { if (!status.ok() && !status.IsNotFound()) { return(GlobalMembers.make_error_code(CryptoNote.error.DataBaseErrorCodes.INTERNAL_ERROR)); } resultStates.Add(status.ok()); } batch.submitRawResult(values, resultStates); return(std::error_code()); }
public void flush(uint8_t data, uint64_t size, ref std::error_code ec) { Debug.Assert(isOpened()); uintptr_t pageSize = (uintptr_t)sysconf(_SC_PAGESIZE); //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: uintptr_t dataAddr = reinterpret_cast <uintptr_t>(data); uintptr_t pageOffset = (dataAddr / pageSize) * pageSize; //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: int result = global::msync(reinterpret_cast <object>(pageOffset), (size_t)(dataAddr % pageSize + size), MS_SYNC); if (result == 0) { result = global::fsync(m_file); if (result == 0) { ec = std::error_code(); return; } } ec = std::error_code(errno, std::system_category()); }
protected static void makeErrorResponse(std::error_code ec, Common.JsonValue resp) { JsonValue error = new JsonValue(JsonValue.OBJECT); JsonValue code = new JsonValue(); code = (long)CryptoNote.JsonRpc.errParseError; //Application specific error code JsonValue message = new JsonValue(); message = ec.message(); JsonValue data = new JsonValue(JsonValue.OBJECT); JsonValue appCode = new JsonValue(); appCode = (long)ec.value(); data.insert("application_code", appCode); error.insert("code", code); error.insert("message", message); error.insert("data", data); resp.insert.functorMethod("error", error); }
public void initCompleted(std::error_code result) { initPromise.set_value(result); }
public override uint onNewBlocks(CompleteBlock[] blocks, uint startHeight, uint count) { Debug.Assert(blocks); Debug.Assert(count > 0); //C++ TO C# CONVERTER TODO TASK: C# does not allow declaring types within methods: // struct Tx // { // TransactionBlockInfo blockInfo; // const ITransactionReader* tx; // bool isLastTransactionInBlock; // }; //C++ TO C# CONVERTER TODO TASK: C# does not allow declaring types within methods: // struct PreprocessedTx : Tx, PreprocessInfo // { // }; List <PreprocessedTx> preprocessedTransactions = new List <PreprocessedTx>(); object preprocessedTransactionsMutex = new object(); uint workers = std::thread.hardware_concurrency(); if (workers == 0) { workers = 2; } BlockingQueue <Tx> inputQueue = new BlockingQueue <Tx>(workers * 2); std::atomic <bool> stopProcessing = new std::atomic <bool>(false); std::atomic <uint> emptyBlockCount = new std::atomic <uint>(0); //C++ TO C# CONVERTER TODO TASK: Lambda expressions cannot be assigned to 'var': var pushingThread = std::async(std::launch.async, () => { for (uint i = 0; i < count && stopProcessing == null; ++i) { auto block = blocks[i].block; if (!block.is_initialized()) { ++emptyBlockCount; continue; } // filter by syncStartTimestamp if (m_syncStart.timestamp != 0 && block.timestamp < m_syncStart.timestamp) { ++emptyBlockCount; continue; } TransactionBlockInfo blockInfo = new TransactionBlockInfo(); blockInfo.height = startHeight + i; blockInfo.timestamp = block.timestamp; blockInfo.transactionIndex = 0; // position in block foreach (var tx in blocks[i].transactions) { var pubKey = tx.GetTransactionPublicKey(); if (pubKey == NULL_PUBLIC_KEY) { ++blockInfo.transactionIndex; continue; } bool isLastTransactionInBlock = blockInfo.transactionIndex + 1 == blocks[i].transactions.size(); Tx item = new Tx(blockInfo, tx.get(), isLastTransactionInBlock); inputQueue.push(new Tx(item)); ++blockInfo.transactionIndex; } } inputQueue.close(); }); //C++ TO C# CONVERTER TODO TASK: Lambda expressions cannot be assigned to 'var': var processingFunction = () => { Tx item = new Tx(); std::error_code ec = new std::error_code(); while (stopProcessing == null && inputQueue.pop(ref item)) { PreprocessedTx output = new PreprocessedTx(); (Tx)output = item; ec.CopyFrom(preprocessOutputs(item.blockInfo, *item.tx, output)); if (ec != null) { stopProcessing = true; break; } lock (preprocessedTransactionsMutex) { preprocessedTransactions.Add(std::move(output)); } } return(ec); }; List <std::future <std::error_code> > processingThreads = new List <std::future <std::error_code> >(); for (uint i = 0; i < workers; ++i) { processingThreads.Add(std::async(std::launch.async, processingFunction)); } std::error_code processingError = new std::error_code(); foreach (var f in processingThreads) { try { std::error_code ec = f.get(); if (processingError == null && ec != null) { //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: processingError = ec; processingError.CopyFrom(ec); } } catch (std::system_error e) { processingError = e.code(); } catch (System.Exception) { processingError = std::make_error_code(std::errc.operation_canceled); } } if (processingError != null) { forEachSubscription((TransfersSubscription sub) => { sub.onError(processingError, startHeight); }); return(0); } //C++ TO C# CONVERTER TODO TASK: The following line was determined to contain a copy constructor call - this should be verified and a copy constructor should be created: //ORIGINAL LINE: ClassicVector<Crypto::Hash> blockHashes = getBlockHashes(blocks, count); List <Crypto.Hash> blockHashes = GlobalMembers.getBlockHashes(new CryptoNote.CompleteBlock(blocks), count); m_observerManager.notify(IBlockchainConsumerObserver.onBlocksAdded, this, blockHashes); // sort by block height and transaction index in block //C++ TO C# CONVERTER TODO TASK: The 'Compare' parameter of std::sort produces a boolean value, while the .NET Comparison parameter produces a tri-state result: //ORIGINAL LINE: std::sort(preprocessedTransactions.begin(), preprocessedTransactions.end(), [](const PreprocessedTx& a, const PreprocessedTx& b) preprocessedTransactions.Sort((PreprocessedTx a, PreprocessedTx b) => { return(std::tie(a.blockInfo.height, a.blockInfo.transactionIndex) < std::tie(b.blockInfo.height, b.blockInfo.transactionIndex)); }); uint processedBlockCount = (uint)emptyBlockCount; try { foreach (var tx in preprocessedTransactions) { processTransaction(tx.blockInfo, *tx.tx, tx); if (tx.isLastTransactionInBlock) { ++processedBlockCount; m_logger.functorMethod(TRACE) << "Processed block " << (int)processedBlockCount << " of " << (int)count << ", last processed block index " << tx.blockInfo.height << ", hash " << blocks[processedBlockCount - 1].blockHash; var newHeight = startHeight + processedBlockCount - 1; //C++ TO C# CONVERTER TODO TASK: Only lambda expressions having all locals passed by reference can be converted to C#: //ORIGINAL LINE: forEachSubscription([newHeight](TransfersSubscription& sub) forEachSubscription((TransfersSubscription sub) => { sub.advanceHeight(newHeight); }); } } } catch (MarkTransactionConfirmedException e) { m_logger.functorMethod(ERROR, BRIGHT_RED) << "Failed to process block transactions: failed to confirm transaction " << e.getTxHash() << ", remove this transaction from all containers and transaction pool"; forEachSubscription((TransfersSubscription sub) => { sub.deleteUnconfirmedTransaction(e.getTxHash()); }); m_poolTxs.erase(e.getTxHash()); } catch (System.Exception e) { m_logger.functorMethod(ERROR, BRIGHT_RED) << "Failed to process block transactions, exception: " << e.Message; } catch { m_logger.functorMethod(ERROR, BRIGHT_RED) << "Failed to process block transactions, unknown exception"; } if (processedBlockCount < count) { uint detachIndex = startHeight + processedBlockCount; m_logger.functorMethod(ERROR, BRIGHT_RED) << "Not all block transactions are processed, fully processed block count: " << (int)processedBlockCount << " of " << (int)count << ", last processed block hash " << (processedBlockCount > 0 ? blocks[processedBlockCount - 1].blockHash : GlobalMembers.NULL_HASH) << ", detach block index " << (int)detachIndex << " to remove partially processed block"; //C++ TO C# CONVERTER TODO TASK: Only lambda expressions having all locals passed by reference can be converted to C#: //ORIGINAL LINE: forEachSubscription([detachIndex](TransfersSubscription& sub) forEachSubscription((TransfersSubscription sub) => { sub.onBlockchainDetach(detachIndex); }); } return(processedBlockCount); }
public void Dispose() { std::error_code ignore = new std::error_code(); close(ref ignore); }