public DataEntry(string key, ETag lastOwner, List<int> senderPath) { this.key = key; this.lastOwnerID = lastOwner.UID; this.lastOwnerRevision = lastOwner.Revision; this.senderPath = senderPath; }
public DataHeader(string key, ETag version, List<int> sentFrom) { this.key = key; this.lastOwnerID = version.UID; this.lastOwnerRevision = version.Revision; this.sentFrom = sentFrom; }
public DataHeader(string key, ETag version, int sentFromID) { this.key = key; this.lastOwnerID = version.UID; this.lastOwnerRevision = version.Revision; this.sentFrom = new List<int>() { sentFromID }; }
public DataEntry(string key, object value, ETag lastOwner, List<int> senderPath,bool subscribed) { this.key = key; this.value = value; this.lastOwnerID = lastOwner.UID; this.lastOwnerRevision = lastOwner.Revision; this.senderPath = senderPath; this.subscribed = subscribed; DetectTypeFromValue(); }
public static ETagCompare CompareETags(ETag first, ETag second) { if (first.Revision > second.Revision) { return ETagCompare.FirstIsNewer; } else if (first.Revision < second.Revision) { return ETagCompare.SecondIsNewer; } else if (first.UID == second.UID) { return ETagCompare.Same; } else { return ETagCompare.Conflict; } }
private void WriteMethodPush(string resource,List<int> senderList, List<int> proxyResponsePath, int contentLength, string mimeType, ETag lastVer, bool isDeleted, bool willClose, MemoryStream bufferedOutput) { StreamWriter writer = new StreamWriter(bufferedOutput, Encoding.ASCII); writer.NewLine = NEWLINE; if (isDeleted) { WriteMethodDeleted(bufferedOutput, resource, senderList, proxyResponsePath, lastVer.UID, lastVer.Revision); } else { WriteMethodHeader(writer, resource, mimeType, contentLength, lastVer.UID, lastVer.Revision, senderList, proxyResponsePath, willClose); } }
/// <summary> /// TODO: add in some code to reduce round-trips to simple data types /// </summary> /// <param name="reader">File to read</param> /// <param name="sentFromList">Sent from list</param> /// <param name="getEntriesFromSender">This function fills in a list of entries that need to be requested from the sender</param> /// <param name="addEntriesToSender">These are entries that the sender does not know about</param> /// <seealso cref="ReadHeadStub"/> private void ReadDictionaryTextFile(StreamReader reader, List<int> sentFromList, List<DataHeader> getEntriesFromSender, List<SendMemoryToPeer> addEntriesToSender) { // 0 - key name // 1 - owner // 2 - revision // 3 - rw flag // 4 - MIME type // WriteDebug(this.local_uid + " ReadDictionaryTextFile"); string nsLine = reader.ReadLine(); string[] nsLineParts = nsLine.Split('\t'); System.Diagnostics.Debug.Assert(nsLineParts[0] == DATA_NAMESPACE + "/"); // if the owner of the dictionary is the same as myself, skip reading the changes if (nsLineParts[1] == this.local_uid.ToString()) { throw new NotSupportedException("ReadDictionaryTextFile cannot read itself");// i want to see if this actually can happen (only when multiple connections happen on the same server) } int itemCount = int.Parse(nsLineParts[4]); // count of all the items in the dictionary List<DataEntry> entriesCovered = new List<DataEntry>(itemCount + this.data.Count); for (int i = 0; i < itemCount; i++) { nsLine = reader.ReadLine(); nsLineParts = nsLine.Split('\t'); //WriteDebug(nsLine); DataHeader getEntry = null; SendMemoryToPeer addEntryToSender = null; ETag tag = new ETag(int.Parse(nsLineParts[1]), int.Parse(nsLineParts[2])); // this entry is used only to call ReadMimeSimpleData DataEntry fakeEntry = new DataEntry("/fake", tag, new List<int>(0)); fakeEntry.ReadMimeSimpleData(nsLineParts[4]); dataLock.EnterReadLock(); try { if (this.data.ContainsKey(nsLineParts[0])) { entriesCovered.Add(this.data[nsLineParts[0]]); } } finally { dataLock.ExitReadLock(); } // the dictionary does not report the current sender so let's tack it on List<int> listOfSenders = new List<int>(GetArrayOf(nsLineParts[5])); if (!listOfSenders.Contains(this.remote_uid)) listOfSenders.Add(this.remote_uid); ResponseAction action = ReadDataStub(nsLineParts[0], fakeEntry.GetMime(), nsLineParts[1] + "." + nsLineParts[2], new List<int>( listOfSenders), out getEntry, out addEntryToSender); if (getEntry != null) { getEntriesFromSender.Add(getEntry); } if (addEntryToSender != null) { addEntriesToSender.Add(addEntryToSender); } if (action == ResponseAction.ForwardToAll) { listOfSenders.Clear(); } if (action != ResponseAction.DoNotForward) { DataEntry get = P2PDictionary.GetEntry( this.data, this.dataLock, nsLineParts[0]); System.Diagnostics.Debug.Assert(get != null); listOfSenders.Add(this.local_uid); SendBroadcastMemory msg = new SendBroadcastMemory(get.key , listOfSenders); WriteMethodPush(get.key, listOfSenders, null, 0, get.GetMime(), get.GetETag(), get.IsEmpty, false, msg.MemBuffer); this.controller.BroadcastToWire(msg); } } // now check to see which dictionary entries that the sender does not have; i'll send my entries to the caller this.dataLock.EnterWriteLock(); try { foreach (KeyValuePair<string, DataEntry> senderDoesNotHave in this.data.SkipWhile(x => entriesCovered.Contains(x.Value))) { DataEntry get = senderDoesNotHave.Value; // i know about something that the sender does not know SendMemoryToPeer mem = new SendMemoryToPeer(get.key, sentFromList); WriteMethodPush(get.key, GetListOfThisLocalID(), null, 0, get.GetMime(), get.GetETag(), get.IsEmpty, false, mem.MemBuffer); addEntriesToSender.Add(mem); } } finally { this.dataLock.ExitWriteLock();} }