/// <summary>Adds the given plan to the plan cache.</summary> /// <remarks> /// The plan is not contained within the cache after this call, it is assumed in use by the client. /// This call simply reserves storage and marks the plan as referenced for the LRU. /// </remarks> public void Add(ServerProcess process, string statement, int contextHashCode, ServerPlan plan) { CachedPlans bumped = null; CachedPlanHeader header = GetPlanHeader(process, statement, contextHashCode); plan.Header = header; plan.PlanCacheTimeStamp = process.Catalog.PlanCacheTimeStamp; lock (this) { if (_plans != null) { CachedPlans plans; if (!_plans.TryGetValue(header, out plans)) { plans = new CachedPlans(); } bumped = _plans.Reference(header, plans); } } if (bumped != null) { DisposeCachedPlans(process, bumped); } }
private void DisposeCachedPlans(ServerProcess process, CachedPlans plans) { foreach (ServerPlan plan in plans) { DisposeCachedPlan(process, plan); } }
/// <summary>Gets a cached plan for the given statement, if available.</summary> /// <remarks> /// If a plan is found, it is referenced for the LRU, and disowned by the cache. /// The client must call Release to return the plan to the cache. /// If no plan is found, null is returned and the cache is unaffected. /// </remarks> public ServerPlan Get(ServerProcess process, string statement, int contextHashCode) { ServerPlan plan = null; CachedPlanHeader header = GetPlanHeader(process, statement, contextHashCode); CachedPlans bumped = null; lock (this) { if (_plans != null) { CachedPlans plans; if (_plans.TryGetValue(header, out plans)) { for (int planIndex = plans.Count - 1; planIndex >= 0; planIndex--) { plan = plans[planIndex]; plans.RemoveAt(planIndex); if (process.Catalog.PlanCacheTimeStamp > plan.PlanCacheTimeStamp) { DisposeCachedPlan(process, plan); plan = null; } else { bumped = _plans.Reference(header, plans); break; } } } } } if (bumped != null) { DisposeCachedPlans(process, bumped); } if (plan != null) { plan.BindToProcess(process); } return(plan); }