private bool AgeCookies(string domain) {
// border case => shrinked to zero
if(m_maxCookies == 0 || m_maxCookiesPerDomain == 0) {
m_domainTable = new Hashtable();
m_count = 0;
return false;
}
int removed = 0;
DateTime oldUsed = DateTime.MaxValue;
DateTime tempUsed;
CookieCollection lruCc = null;
string lruDomain = null;
string tempDomain = null;
PathList pathList;
int domain_count = 0;
int itemp = 0;
float remainingFraction = 1.0F;
// the container was shrinked, might need additional cleanup for each domain
if (m_count > m_maxCookies) {
// Means the fraction of the container to be left
// Each domain will be cut accordingly
remainingFraction = (float)m_maxCookies/(float)m_count;
}
foreach (DictionaryEntry entry in m_domainTable) {
if (domain == null) {
tempDomain = (string) entry.Key;
pathList = (PathList) entry.Value; //aliasing to trick foreach
}
else {
tempDomain = domain;
pathList = (PathList) m_domainTable[domain];
}
domain_count = 0; // cookies in the domain
foreach (CookieCollection cc in pathList.Values) {
itemp = ExpireCollection(cc);
removed += itemp;
m_count -= itemp; //update this container count;
domain_count += cc.Count;
// we also find the least used cookie collection in ENTIRE container
// we count the collection as LRU only if it holds 1+ elements
if (cc.Count > 0 && (tempUsed = cc.TimeStamp(CookieCollection.Stamp.Check)) < oldUsed) {
lruDomain = tempDomain;
lruCc = cc;
oldUsed = tempUsed;
}
}
// Check if we have reduced to the limit of the domain by expiration only
int min_count = Math.Min((int)(domain_count*remainingFraction), Math.Min(m_maxCookiesPerDomain, m_maxCookies)-1);
if (domain_count > min_count) {
//That case require sorting all domain collections by timestamp
Array cookies = Array.CreateInstance(typeof(CookieCollection), pathList.Count);
Array stamps = Array.CreateInstance(typeof(DateTime), pathList.Count);
foreach (CookieCollection cc in pathList.Values) {
stamps.SetValue(cc.TimeStamp(CookieCollection.Stamp.Check), itemp);
cookies.SetValue(cc ,itemp );
++itemp ;
}
Array.Sort(stamps, cookies);
itemp = 0;
for (int i = 0; i < pathList.Count; ++i) {
CookieCollection cc = (CookieCollection)cookies.GetValue(i);
lock (cc) {
while (domain_count > min_count && cc.Count > 0) {
cc.RemoveAt(0);
--domain_count;
--m_count;
++removed;
}
}
if (domain_count <= min_count ) {
break;
}
}
if (domain_count > min_count && domain != null) {
//cannot complete aging of explicit domain (no cookie adding allowed)
return false;
}
}
// we have completed aging of specific domain
if (domain != null) {
return true;
}
}
// The rest is for entire container aging
// We must get at least one free slot.
//Don't need to appy LRU if we already cleaned something
if (removed != 0) {
return true;
}
if (oldUsed == DateTime.MaxValue) {
//Something strange. Either capacity is 0 or all collections are locked with cc.Used
return false;
}
// Remove oldest cookies from the least used collection
lock (lruCc) {
while (m_count >= m_maxCookies && lruCc.Count > 0) {
lruCc.RemoveAt(0);
--m_count;
}
}
return true;
}