Esempio n. 1
0
 /// <summary>
 /// Returns the current representative of the set this node is in.
 /// Note that the representative is only accurate untl the next Union operation.
 /// </summary>
 public UnionFindNode Find()
 {
     if (!ReferenceEquals(_parent, this))
     {
         _parent = _parent.Find();
     }
     return(_parent);
 }
Esempio n. 2
0
 /// <summary>
 /// Determines whether or not this node and the other node are in the same set.
 /// </summary>
 public bool IsUnionedWith(UnionFindNode other)
 {
     if (other == null)
     {
         throw new ArgumentNullException("other");
     }
     return(ReferenceEquals(Find(), other.Find()));
 }
Esempio n. 3
0
        //TODO: for testnet we only have a single chain, thus grouper only take care of txList in one chain (hence Process has chainId as parameter)
        public async Task <Tuple <List <List <Transaction> >, Dictionary <Transaction, Exception> > > ProcessNaive(Hash chainId, List <Transaction> transactions)
        {
            var txResourceHandle = new Dictionary <Transaction, string>();
            var failedTxs        = new Dictionary <Transaction, Exception>();

            if (transactions.Count == 0)
            {
                return(new Tuple <List <List <Transaction> >, Dictionary <Transaction, Exception> >(new List <List <Transaction> >(), failedTxs));
            }

            Dictionary <string, UnionFindNode> resourceUnionSet = new Dictionary <string, UnionFindNode>();

            //set up the union find set as the representation of graph and the connected components will be the resulting groups
            foreach (var tx in transactions)
            {
                UnionFindNode first = null;
                List <string> resources;
                try
                {
                    resources = (await _resourceUsageDetectionService.GetResources(chainId, tx)).ToList();
                }
                catch (Exception e)
                {
                    failedTxs.Add(tx, e);
                    continue;
                }

                //_logger.Debug(string.Format("tx {0} have resource [{1}]", tx.From, string.Join(" ||| ", resources)));
                foreach (var resource in resources)
                {
                    if (!resourceUnionSet.TryGetValue(resource, out var node))
                    {
                        node = new UnionFindNode();
                        resourceUnionSet.Add(resource, node);
                    }
                    if (first == null)
                    {
                        first = node;
                        txResourceHandle.Add(tx, resource);
                    }
                    else
                    {
                        node.Union(first);
                    }
                }
            }

            Dictionary <int, List <Transaction> > grouped = new Dictionary <int, List <Transaction> >();
            List <List <Transaction> >            result  = new List <List <Transaction> >();

            foreach (var tx in transactions)
            {
                if (txResourceHandle.TryGetValue(tx, out var firstResource))
                {
                    int nodeId = resourceUnionSet[firstResource].Find().NodeId;
                    if (!grouped.TryGetValue(nodeId, out var group))
                    {
                        group = new List <Transaction>();
                        grouped.Add(nodeId, group);
                    }
                    group.Add(tx);
                }
                else
                {
                    if (!failedTxs.ContainsKey(tx))
                    {
                        //each "resource-free" transaction have its own group
                        result.Add(new List <Transaction>()
                        {
                            tx
                        });
                    }
                }
            }
            result.AddRange(grouped.Values);

            _logger?.Info(string.Format(
                              "Grouper on chainId \"{0}\" group [{1}] transactions into [{2}] groups with sizes [{3}], There are also {4} transactions failed retriving resource", chainId.DumpHex(),
                              transactions.Count, result.Count, string.Join(", ", result.Select(a => a.Count)), failedTxs.Count));

            return(new Tuple <List <List <Transaction> >, Dictionary <Transaction, Exception> >(result, failedTxs));;
        }
Esempio n. 4
0
 /// <summary>
 /// Creates a new disjoint node, representative of a set containing only the new node.
 /// </summary>
 public UnionFindNode()
 {
     _parent = this;
     NodeId  = Interlocked.Increment(ref _nextId);
 }