Beispiel #1
0
        /// <summary>
        /// Initialise a ChunkDataWrapper when the ChunkAvailabilityReply is received before associated data.
        /// </summary>
        /// <param name="chunkAvailabilityReply">The matching ChunkAvailabilityReply</param>
        public ChunkDataWrapper(ChunkAvailabilityReply chunkAvailabilityReply)
        {
            if (chunkAvailabilityReply == null)
            {
                throw new Exception("Unable to create a ChunkDataWrapper with a null ChunkAvailabilityReply reference.");
            }

            this.ChunkAvailabilityReply = chunkAvailabilityReply;
            this.TimeCreated            = DateTime.Now;
        }
        /// <summary>
        /// Initialise a ChunkDataWrapper when the ChunkAvailabilityReply is received before associated data.
        /// </summary>
        /// <param name="chunkAvailabilityReply">The matching ChunkAvailabilityReply</param>
        public ChunkDataWrapper(ChunkAvailabilityReply chunkAvailabilityReply)
        {
            if (chunkAvailabilityReply == null)
                throw new Exception("Unable to create a ChunkDataWrapper with a null ChunkAvailabilityReply reference.");

            this.ChunkAvailabilityReply = chunkAvailabilityReply;
            this.TimeCreated = DateTime.Now;
        }
Beispiel #3
0
        /// <summary>
        /// UDP and TCP - Received when a peer sends us a chunk data information possibly following a request
        /// </summary>
        /// <param name="packetHeader"></param>
        /// <param name="connection"></param>
        /// <param name="incomingReply"></param>
        private static void IncomingChunkInterestReplyInfo(PacketHeader packetHeader, Connection connection, ChunkAvailabilityReply incomingReply)
        {
            try
            {
                ConnectionInfo incomingConnectionInfo = new ConnectionInfo(connection.ConnectionInfo.ConnectionType, incomingReply.SourceNetworkIdentifier, connection.ConnectionInfo.RemoteEndPoint, true);
                if (DFS.loggingEnabled) DFS._DFSLogger.Trace("IncomingChunkInterestReplyInfo from " + connection + " for item " + incomingReply.ItemCheckSum + ", chunkIndex " + incomingReply.ChunkIndex + ".");

                if (incomingReply.ReplyState == ChunkReplyState.DataIncluded && incomingReply.PacketIdentifier == null)
                    throw new ArgumentNullException("The specified packet identifier cannot be null.");

                DistributedItem item = null;
                lock (globalDFSLocker)
                {
                    if (swarmedItemsDict.ContainsKey(incomingReply.ItemCheckSum))
                        item = swarmedItemsDict[incomingReply.ItemCheckSum];
                }

                if (item != null)
                {
                    //Do we have the data yet?
                    bool handleReply = false;
                    lock (chunkDataCacheLocker)
                    {
                        //We generally expect the data to arrive first, but we handle both situations anyway
                        //Realistic testing across a 100MB connection shows that we already have the data 90.1% of the time
                        if (incomingReply.ReplyState == ChunkReplyState.DataIncluded && 
                            chunkDataCache.ContainsKey(incomingReply.SourceNetworkIdentifier) && 
                            chunkDataCache[incomingReply.SourceNetworkIdentifier].ContainsKey(incomingReply.PacketIdentifier))
                        {
                            incomingReply.SetChunkData(chunkDataCache[incomingReply.SourceNetworkIdentifier][incomingReply.PacketIdentifier].Data);
                            chunkDataCache[incomingReply.SourceNetworkIdentifier].Remove(incomingReply.PacketIdentifier);

                            if (DFS.loggingEnabled) DFS._DFSLogger.Debug("Completed ChunkAvailabilityReply using data in chunkDataCache from " + connection + ", packet identifier:" + incomingReply.PacketIdentifier + ".");

                            if (chunkDataCache[incomingReply.SourceNetworkIdentifier].Count == 0)
                                chunkDataCache.Remove(incomingReply.SourceNetworkIdentifier);
                        }
                        else if (incomingReply.ReplyState == ChunkReplyState.DataIncluded)
                        {
                            //We have beaten the data, we will add the chunk availability reply instead and wait, letting the incoming data trigger the handle
                            if (!chunkDataCache.ContainsKey(incomingReply.SourceNetworkIdentifier))
                                chunkDataCache.Add(incomingReply.SourceNetworkIdentifier, new Dictionary<string,ChunkDataWrapper>());

                            chunkDataCache[incomingReply.SourceNetworkIdentifier].Add(incomingReply.PacketIdentifier, new ChunkDataWrapper(incomingReply));
                            if (DFS.loggingEnabled) DFS._DFSLogger.Debug("Added ChunkAvailabilityReply to chunkDataCache (awaiting data) from " + connection + ", packet identifier:" + incomingReply.PacketIdentifier + ".");
                        }

                        //We decide if we are going to handle the data within the lock to avoid possible handle contention
                        if (incomingReply.ChunkDataSet || incomingReply.ReplyState != ChunkReplyState.DataIncluded)
                            handleReply = true;
                    }

                    if (handleReply)
                    {
                        incomingReply.SetSourceConnectionInfo(incomingConnectionInfo);
                        item.HandleIncomingChunkReply(incomingReply);
                    }
                }
            }
            catch (Exception e)
            {
                LogTools.LogException(e, "Error_IncomingChunkInterestReplyInfo");
            }
        }