diff --git a/Common/ConfigurationExtension.cs b/Common/ConfigurationExtension.cs index 8a47505a1..116aae9f3 100644 --- a/Common/ConfigurationExtension.cs +++ b/Common/ConfigurationExtension.cs @@ -58,6 +58,24 @@ public static string GetValue(this NameValueCollection collection, string key, s public static void Deserialize(this TElement section, XmlReader reader) where TElement : ConfigurationElement { + if (section is ConfigurationElementCollection) + { + var collectionType = section.GetType(); + var att = collectionType.GetCustomAttributes(typeof(ConfigurationCollectionAttribute), true).FirstOrDefault() as ConfigurationCollectionAttribute; + + if (att != null) + { + var property = collectionType.GetProperty("AddElementName", BindingFlags.NonPublic | BindingFlags.Instance); + property.SetValue(section, att.AddItemName, null); + + property = collectionType.GetProperty("RemoveElementName", BindingFlags.NonPublic | BindingFlags.Instance); + property.SetValue(section, att.RemoveItemName, null); + + property = collectionType.GetProperty("ClearElementName", BindingFlags.NonPublic | BindingFlags.Instance); + property.SetValue(section, att.ClearItemsName, null); + } + } + var deserializeElementMethod = typeof(TElement).GetMethod("DeserializeElement", BindingFlags.NonPublic | BindingFlags.Instance); deserializeElementMethod.Invoke(section, new object[] { reader, false }); } diff --git a/Common/SmartPool.cs b/Common/SmartPool.cs index df3cfc098..2b01ea2a2 100644 --- a/Common/SmartPool.cs +++ b/Common/SmartPool.cs @@ -9,20 +9,10 @@ namespace SuperSocket.Common { /// - /// The basic interface of smart pool + /// The pool information class /// - /// - public interface ISmartPool + public interface IPoolInfo { - /// - /// Initializes the specified min pool size. - /// - /// The min size of the pool. - /// The max size of the pool. - /// The source creator. - /// - void Initialize(int minPoolSize, int maxPoolSize, ISmartPoolSourceCreator sourceCreator); - /// /// Gets the min size of the pool. /// @@ -48,6 +38,31 @@ public interface ISmartPool /// int AvialableItemsCount { get; } + + /// + /// Gets the total items count, include items in the pool and outside the pool. + /// + /// + /// The total items count. + /// + int TotalItemsCount { get; } + } + + /// + /// The basic interface of smart pool + /// + /// + public interface ISmartPool : IPoolInfo + { + /// + /// Initializes the specified min pool size. + /// + /// The min size of the pool. + /// The max size of the pool. + /// The source creator. + /// + void Initialize(int minPoolSize, int maxPoolSize, ISmartPoolSourceCreator sourceCreator); + /// /// Pushes the specified item into the pool. /// @@ -186,6 +201,19 @@ public int AvialableItemsCount } } + private int m_TotalItemsCount; + + /// + /// Gets the total items count, include items in the pool and outside the pool. + /// + /// + /// The total items count. + /// + public int TotalItemsCount + { + get { return m_TotalItemsCount; } + } + /// /// Initializes the specified min and max pool size. /// @@ -228,8 +256,12 @@ public void Initialize(int minPoolSize, int maxPoolSize, ISmartPoolSourceCreator { m_GlobalStack.Push(items[i]); } + + m_TotalItemsCount = m_MinPoolSize; } + private int m_IsIncreasing = 0; + /// /// Pushes the specified item into the pool. /// @@ -239,6 +271,24 @@ public void Push(T item) m_GlobalStack.Push(item); } + bool TryPopWithWait(out T item, int waitTicks) + { + var spinWait = new SpinWait(); + + while (true) + { + spinWait.SpinOnce(); + + if (m_GlobalStack.TryPop(out item)) + return true; + + if (spinWait.Count >= waitTicks) + { + return false; + } + } + } + /// /// Tries to get one item from the pool. /// @@ -253,42 +303,43 @@ public bool TryGet(out T item) var currentSourceCount = m_CurrentSourceCount; if (currentSourceCount >= m_ItemsSource.Length) - return false; - - if (Interlocked.CompareExchange(ref m_CurrentSourceCount, currentSourceCount + 1, currentSourceCount) != currentSourceCount) { - var spinWait = new SpinWait(); + return TryPopWithWait(out item, 100); + } - while (true) - { - spinWait.SpinOnce(); + var isIncreasing = m_IsIncreasing; - if (m_GlobalStack.TryPop(out item)) - return true; + if (isIncreasing == 1) + return TryPopWithWait(out item, 100); - if (spinWait.Count >= 100) - return false; - } - } + if (Interlocked.CompareExchange(ref m_IsIncreasing, 1, isIncreasing) != isIncreasing) + return TryPopWithWait(out item, 100); + + IncreaseCapacity(); - int totalItemsCount = 0; + m_IsIncreasing = 0; - for (var i = 0; i < currentSourceCount; i++) + if (!m_GlobalStack.TryPop(out item)) { - totalItemsCount += m_ItemsSource[i].Count; + return false; } - totalItemsCount = Math.Min(totalItemsCount, m_MaxPoolSize - totalItemsCount); + return true; + } + + private void IncreaseCapacity() + { + var newItemsCount = Math.Min(m_TotalItemsCount, m_MaxPoolSize - m_TotalItemsCount); T[] items; - m_ItemsSource[currentSourceCount] = m_SourceCreator.Create(totalItemsCount, out items); + m_ItemsSource[m_CurrentSourceCount] = m_SourceCreator.Create(newItemsCount, out items); + + m_TotalItemsCount += newItemsCount; for (var i = 0; i < items.Length; i++) { m_GlobalStack.Push(items[i]); } - - return m_GlobalStack.TryPop(out item); } } } diff --git a/Facility/HttpBase/HttpReceiveFilterBase.cs b/Facility/HttpBase/HttpReceiveFilterBase.cs deleted file mode 100644 index feb1f7469..000000000 --- a/Facility/HttpBase/HttpReceiveFilterBase.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Linq; -using System.Text; -using SuperSocket.Common; -using SuperSocket.SocketBase; -using SuperSocket.SocketBase.Protocol; - -namespace SuperSocket.Facility.HttpBase -{ - /// - /// HttpReceiveFilterBase - /// - /// The type of the request info. - public abstract class HttpReceiveFilterBase : TerminatorReceiveFilter - where TRequestInfo : IRequestInfo - { - /// - /// Http header terminator - /// - private static readonly byte[] NewLine = Encoding.ASCII.GetBytes("\r\n\r\n"); - - /// - /// indicate whether the header has been parsed - /// - private bool m_HeaderParsed = false; - - /// - /// Gets the header items. - /// - protected NameValueCollection HeaderItems { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - protected HttpReceiveFilterBase(IAppSession session) - : base(session, NewLine) - { - - } - - /// - /// Filters the specified session. - /// - /// The read buffer. - /// The offset. - /// The length. - /// if set to true [to be copied]. - /// The rest. - /// - public override TRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest) - { - if (!m_HeaderParsed) - { - return base.Filter(readBuffer, offset, length, toBeCopied, out rest); - } - else - { - return FilterRequestBody(readBuffer, offset, length, toBeCopied, out rest); - } - } - - /// - /// Filters the request body. - /// - /// The read buffer. - /// The offset. - /// The length. - /// if set to true [to be copied]. - /// The rest data size. - /// - protected abstract TRequestInfo FilterRequestBody(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest); - - /// - /// Resolves the specified data. - /// - /// The data. - /// The offset. - /// The length. - /// - protected override TRequestInfo ProcessMatchedRequest(byte[] data, int offset, int length) - { - string header = Encoding.UTF8.GetString(data, offset, length); - - var headerItems = new NameValueCollection(); - MimeHeaderHelper.ParseHttpHeader(header, headerItems); - HeaderItems = headerItems; - - OnHeaderParsed(headerItems); - - return NullRequestInfo; - } - - /// - /// Called when [header parsed]. - /// - /// The header. - protected virtual void OnHeaderParsed(NameValueCollection header) - { - - } - - /// - /// Resets this instance to inital state. - /// - public override void Reset() - { - m_HeaderParsed = false; - HeaderItems = null; - base.Reset(); - } - } -} diff --git a/Facility/HttpBase/HttpRequestInfoBase.cs b/Facility/HttpBase/HttpRequestInfoBase.cs deleted file mode 100644 index 2e72ed886..000000000 --- a/Facility/HttpBase/HttpRequestInfoBase.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SuperSocket.SocketBase.Protocol; -using System.Collections.Specialized; - -namespace SuperSocket.Facility.HttpBase -{ - /// - /// IHttpRequestInfo - /// - public interface IHttpRequestInfo : IRequestInfo - { - /// - /// Gets the http header. - /// - NameValueCollection Header { get; } - } - - /// - /// HttpRequestInfoBase - /// - public abstract class HttpRequestInfoBase : IHttpRequestInfo - { - /// - /// Gets the key of this request. - /// - public string Key { get; private set; } - - /// - /// Gets the http header. - /// - public NameValueCollection Header { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The key. - /// The header. - protected HttpRequestInfoBase(string key, NameValueCollection header) - { - Key = key; - Header = header; - } - } - - /// - /// HttpRequestInfoBase - /// - /// The type of the request body. - public abstract class HttpRequestInfoBase : HttpRequestInfoBase - { - /// - /// Gets the body. - /// - public TRequestBody Body { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The key. - /// The header. - /// The body. - protected HttpRequestInfoBase(string key, NameValueCollection header, TRequestBody body) - : base(key, header) - { - Body = body; - } - } -} diff --git a/Facility/HttpBase/MimeHeaderHelper.cs b/Facility/HttpBase/MimeHeaderHelper.cs deleted file mode 100644 index 63be598bc..000000000 --- a/Facility/HttpBase/MimeHeaderHelper.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Linq; -using System.Text; - -namespace SuperSocket.Facility.HttpBase -{ - /// - /// MimeHeader Helper class - /// - public static class MimeHeaderHelper - { - private const string Tab = "\t"; - private const char Colon = ':'; - private const string Space = " "; - private const string ValueSeparator = ", "; - - /// - /// Parses the HTTP header. - /// - /// The header data. - /// The header. - public static void ParseHttpHeader(string headerData, NameValueCollection header) - { - string line; - string firstLine = string.Empty; - string prevKey = string.Empty; - - var reader = new StringReader(headerData); - - while (!string.IsNullOrEmpty(line = reader.ReadLine())) - { - if (string.IsNullOrEmpty(firstLine)) - { - firstLine = line; - continue; - } - - if (line.StartsWith(Tab) && !string.IsNullOrEmpty(prevKey)) - { - string currentValue = header[prevKey]; - header[prevKey] = currentValue + line.Trim(); - continue; - } - - int pos = line.IndexOf(Colon); - - if (pos <= 0) - continue; - - string key = line.Substring(0, pos); - - if (!string.IsNullOrEmpty(key)) - key = key.Trim(); - - var valueOffset = pos + 1; - - if (line.Length <= valueOffset) //No value in this line - continue; - - string value = line.Substring(valueOffset); - if (!string.IsNullOrEmpty(value) && value.StartsWith(Space) && value.Length > 1) - value = value.Substring(1); - - if (string.IsNullOrEmpty(key)) - continue; - - string oldValue = header[key]; - - if (string.IsNullOrEmpty(oldValue)) - { - header.Add(key, value); - } - else - { - header[key] = oldValue + ValueSeparator + value; - } - - prevKey = key; - } - } - } -} diff --git a/Facility/Protocol/CountSpliterReceiveFilter.cs b/Facility/Protocol/CountSpliterReceiveFilter.cs index 5ffbc62fe..f2e84495a 100644 --- a/Facility/Protocol/CountSpliterReceiveFilter.cs +++ b/Facility/Protocol/CountSpliterReceiveFilter.cs @@ -160,7 +160,7 @@ public void Reset() /// /// The filter state. /// - public FilterState State { get; private set; } + public FilterState State { get; protected set; } } /// diff --git a/Facility/Protocol/FixedSizeReceiveFilter.cs b/Facility/Protocol/FixedSizeReceiveFilter.cs index d7e964d88..cede1b4df 100644 --- a/Facility/Protocol/FixedSizeReceiveFilter.cs +++ b/Facility/Protocol/FixedSizeReceiveFilter.cs @@ -10,7 +10,7 @@ namespace SuperSocket.Facility.Protocol /// FixedSizeReceiveFilter /// /// The type of the request info. - public abstract class FixedSizeReceiveFilter : IReceiveFilter, IOffsetAdapter + public abstract class FixedSizeReceiveFilter : IReceiveFilter, IOffsetAdapter, IReceiveFilterInitializer where TRequestInfo : IRequestInfo { private int m_ParsedLength; @@ -39,6 +39,13 @@ protected FixedSizeReceiveFilter(int size) m_Size = size; } + private int m_OrigOffset; + + void IReceiveFilterInitializer.Initialize(IAppServer appServer, IAppSession session) + { + m_OrigOffset = session.SocketSession.OrigReceiveOffset; + } + /// /// Filters the specified session. /// @@ -54,7 +61,7 @@ public virtual TRequestInfo Filter(byte[] readBuffer, int offset, int length, bo if (rest >= 0) { - var requestInfo = ProcessMatchedRequest(readBuffer, offset - m_ParsedLength, m_ParsedLength + length, toBeCopied); + var requestInfo = ProcessMatchedRequest(readBuffer, offset - m_ParsedLength, m_Size, toBeCopied); InternalReset(); return requestInfo; } @@ -63,6 +70,15 @@ public virtual TRequestInfo Filter(byte[] readBuffer, int offset, int length, bo m_ParsedLength += length; m_OffsetDelta = m_ParsedLength; rest = 0; + + var expectedOffset = offset + length; + var newOffset = m_OrigOffset + m_OffsetDelta; + + if (newOffset < expectedOffset) + { + Buffer.BlockCopy(readBuffer, offset - m_ParsedLength + length, readBuffer, m_OrigOffset, m_ParsedLength); + } + return NullRequestInfo; } } @@ -113,7 +129,7 @@ int IOffsetAdapter.OffsetDelta /// /// The filter state. /// - public FilterState State { get; private set; } + public FilterState State { get; protected set; } private void InternalReset() { diff --git a/Facility/SuperSocket.Facility.Net35.csproj b/Facility/SuperSocket.Facility.Net35.csproj index 3da787a8d..194c35d55 100644 --- a/Facility/SuperSocket.Facility.Net35.csproj +++ b/Facility/SuperSocket.Facility.Net35.csproj @@ -55,9 +55,6 @@ GlobalAssemblyInfo.cs - - - diff --git a/Facility/SuperSocket.Facility.Net40.csproj b/Facility/SuperSocket.Facility.Net40.csproj index e3c962ee8..2d95084f6 100644 --- a/Facility/SuperSocket.Facility.Net40.csproj +++ b/Facility/SuperSocket.Facility.Net40.csproj @@ -51,9 +51,6 @@ GlobalAssemblyInfo.cs - - - diff --git a/Facility/SuperSocket.Facility.Net45.csproj b/Facility/SuperSocket.Facility.Net45.csproj index 067a87a45..12e76901e 100644 --- a/Facility/SuperSocket.Facility.Net45.csproj +++ b/Facility/SuperSocket.Facility.Net45.csproj @@ -54,9 +54,6 @@ GlobalAssemblyInfo.cs - - - diff --git a/Push.bat b/Push.bat index 655830d92..0cca31270 100644 --- a/Push.bat +++ b/Push.bat @@ -1,3 +1,3 @@ -git push origin -git push github +git push origin v1.5:v1.5 +git push github v1.5:v1.5 pause \ No newline at end of file diff --git a/QuickStart/ServerPush/PushServer.cs b/QuickStart/ServerPush/PushServer.cs index 1d44d1bed..a5f1523fc 100644 --- a/QuickStart/ServerPush/PushServer.cs +++ b/QuickStart/ServerPush/PushServer.cs @@ -11,7 +11,7 @@ public class PushServer : AppServer { private Timer m_PushTimer; - private int m_Interval = 60 * 1000 * 5; //5 minutes + private int m_Interval = 60 * 1000; //1 minute protected override void OnStartup() { diff --git a/QuickStart/ServerPush/ServerPush.csproj b/QuickStart/ServerPush/ServerPush.csproj index c4153745e..da1679858 100644 --- a/QuickStart/ServerPush/ServerPush.csproj +++ b/QuickStart/ServerPush/ServerPush.csproj @@ -34,8 +34,6 @@ - - @@ -50,6 +48,19 @@ {40b77789-ea11-4c05-8f52-86711d7bcaaf} SuperSocket.SocketBase.Net40 + + {153fef72-191c-43d9-be71-2b351c7ac760} + SuperSocket.SocketEngine.Net40 + + + {b9113694-7226-4152-938d-3172b11571a1} + SuperSocket.SocketService.Net40 + + + + + PreserveNewest +