// Query all the entries from the AspNet_SqlCacheTablesForChangeNotification 
        // table and update the values in the cache accordingly.
        //
        // This is mainly called by the timer callback.  But will also be called by
        // UpdateDatabaseNotifState, which polls for changes on demand.
        internal static void PollDatabaseForChanges(DatabaseNotifState dbState, bool fromTimer) {
            SqlDataReader       sqlReader = null;
            SqlConnection       sqlConn = null;
            SqlCommand          sqlCmd = null;
            int                 changeId;
            string              tableName;
            CacheInternal       cacheInternal = HttpRuntime.CacheInternal;
            string              monitorKey;
            object              obj;
            bool                notifEnabled = false;
            Exception           pollExpt = null;
            SqlException        sqlExpt = null;

            Debug.Trace("SqlCacheDependencyManagerPolling", 
                "PollCallback called; connection=" + dbState._connectionString);

            if (s_shutdown) {
                return;
            }

            // If this call is from a timer, and if the refcount for this database is zero,
            // we will ignore it. The exception is if dbState._init == false, 
            // which means the timer is polling it for the first time.
            if (dbState._refCount == 0 && fromTimer && dbState._init  ) {
                Debug.Trace("SqlCacheDependencyManagerPolling", 
                    "PollCallback ignored for " + dbState._database + " because refcount is 0");
                return;
            }

            // Grab the lock, which allows only one thread to enter this method.
            if (Interlocked.CompareExchange(ref dbState._rqInCallback, 1, 0) != 0) {

                // We can't get the lock.
                
                if (!fromTimer) {
                    // A non-timer caller will really want to make a call to SQL and
                    // get the result.  So if another thread is calling this, we'll
                    // wait for it to be done.
                    int         timeout;
                    HttpContext context = HttpContext.Current;

                    if (context == null) {
                        timeout = 30;
                    }
                    else {
                        timeout = Math.Max(context.Timeout.Seconds / 3, 30);
                    }
                    DateTime waitLimit = DateTime.UtcNow.Add(new TimeSpan(0, 0, timeout));
                    
                    for (;;) {
                        if (Interlocked.CompareExchange(ref dbState._rqInCallback, 1, 0) == 0) {
                            break;
                        }
                            
                        Thread.Sleep(250);

                        if (s_shutdown) {
                            return;
                        }

                        // only apply timeout if a managed debugger is not attached
                        if (!System.Diagnostics.Debugger.IsAttached && DateTime.UtcNow > waitLimit) {
                            // We've waited and retried for 5 seconds.
                            // Somehow PollCallback haven't finished its first call for this database
                            // Assume we cannot connect to SQL.
                            throw new HttpException(
                                SR.GetString(SR.Cant_connect_sql_cache_dep_database_polling, dbState._database));
                        }
                    }
                }
                else {
                    // For a timer callback, if another thread is updating the data for
                    // this database, this thread will just leave and let that thread
                    // finish the update job.
                    Debug.Trace("SqlCacheDependencyManagerPolling", 
                        "PollCallback returned because another thread is updating the data");
                    return;
                }
            }

            try {
                try {
                    // Keep a count on how many threads are polling right now
                    // This counter is used by Dispose()
                    Interlocked.Increment(ref s_activePolling);

                    // The below assert was commented out because this method is either
                    // called by a timer thread, or thru the SqlCacheDependencyAdmin APIs.
                    // In the latter case, the caller should have the permissions.
                    //(new SqlClientPermission(PermissionState.Unrestricted)).Assert();

                    dbState.GetConnection(out sqlConn, out sqlCmd);
                    sqlReader = sqlCmd.ExecuteReader();

                    // If we got stuck for a long time in the ExecuteReader above, 
                    // Dispose() may have given up already while waiting for this thread to finish
                    if (s_shutdown) {
                        return;
                    }

                    // ExecuteReader() succeeded, and that means we at least have found the notification table.
                    notifEnabled = true;

                    // Remember the original list of tables that are enabled
                    Hashtable   originalTables = (Hashtable)dbState._tables.Clone();
                    
                    while(sqlReader.Read()) {
                        tableName = sqlReader.GetString(0);
                        changeId = sqlReader.GetInt32(1);
                        
                        Debug.Trace("SqlCacheDependencyManagerPolling", 
                                "Database=" + dbState._database+ "; tableName=" + tableName + "; changeId=" + changeId);

                        monitorKey = GetMoniterKey(dbState._database, tableName);
                        obj = cacheInternal[monitorKey];

                        if (obj == null) {
                            Debug.Assert(!dbState._tables.ContainsKey(tableName), 
                                        "DatabaseNotifStae._tables and internal cache keys should be in-[....]");
                            
                            Debug.Trace("SqlCacheDependencyManagerPolling", 
                                "Add Database=" + dbState._database+ "; tableName=" + tableName + "; changeId=" + changeId);
                            
                            cacheInternal.UtcAdd(monitorKey, changeId, null, 
                                        Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                                        CacheItemPriority.NotRemovable, null);

                            dbState._tables.Add(tableName, null);
                        }
                        else if (changeId != (int)obj) {
                            Debug.Assert(dbState._tables.ContainsKey(tableName), 
                                        "DatabaseNotifStae._tables and internal cache keys should be in-[....]");
                            
                            Debug.Trace("SqlCacheDependencyManagerPolling", 
                                    "Change Database=" + dbState._database+ "; tableName=" + tableName + "; old=" + (int)obj + "; new=" + changeId);
                            
                            // ChangeId is different. It means some table changes have happened.
                            // Update local cache value
                            cacheInternal.UtcInsert(monitorKey, changeId, null, 
                                        Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
                                        CacheItemPriority.NotRemovable, null);
                        }

                        originalTables.Remove(tableName);
                    }

                    // What's left in originalTables are the ones that're no longer
                    // contained in the AspNet_SqlCacheTablesForChangeNotification
                    // table in the database.
                    
                    // Remove tables which are no longer enabled for notification
                    foreach(object key in originalTables.Keys) {
                        dbState._tables.Remove((string)key);
                        cacheInternal.Remove(GetMoniterKey(dbState._database, (string)key));
                        
                        Debug.Trace("SqlCacheDependencyManagerPolling", 
                                "Remove Database=" + dbState._database+ "; key=" + key);
                    }

                    // Clear old error, if any.
                    if (dbState._pollSqlError != 0) {
                        dbState._pollSqlError = 0;
                    }
                }
                catch (Exception e) {
                    pollExpt = e;
                    
                    sqlExpt = e as SqlException;
                    if (sqlExpt != null) {
                        Debug.Trace("SqlCacheDependencyManagerPolling", "Error reading rows.  SqlException:"+
                            "\nMessage=" + sqlExpt.Message +
                            "\nNumber=" + sqlExpt.Number);
                        
                        dbState._pollSqlError = sqlExpt.Number;
                    }
                    else {
                        dbState._pollSqlError = 0;
                        Debug.Trace("SqlCacheDependencyManagerPolling", "Error reading rows.  Exception:"+ pollExpt);
                    }
                }
                finally {
                    try {
                        if (sqlReader != null) {
                            sqlReader.Close();
                        }

                        dbState.ReleaseConnection(ref sqlConn, ref sqlCmd, pollExpt != null);
                    }
                    catch {
                    }

                    // Need locking because EnsureTableIsRegisteredAndPolled() assumes 
                    // the fields in a dbState are set atomically.
                    lock(dbState) {
                        dbState._pollExpt = pollExpt;

                        // If we have changed from being enabled to disabled, and
                        // it's because we cannot find the SP for polling, it means
                        // the database is no longer enabled for sql cache dependency.
                        // we should invalidate all cache items depending on any
                        // table on this database
                        if (dbState._notifEnabled && !notifEnabled && 
                            pollExpt != null && dbState._pollSqlError == SQL_EXCEPTION_SP_NOT_FOUND) {
                            foreach(object key in dbState._tables.Keys) {
                                try {
                                    cacheInternal.Remove(GetMoniterKey(dbState._database, (string)key));
                                }
                                catch {}
                                
                                Debug.Trace("SqlCacheDependencyManagerPolling", 
                                    "Changed to disabled.  Remove Database=" + dbState._database+ "; key=" + key);
                            }

                            // Since we have removed all the cache items related to this database,
                            // the _refCount of this database will drop to zero, and thus the timer
                            // callback will not poll this database.
                            // So we have to cleanup _tables now.
                            dbState._tables.Clear();
                        }
                        
                        dbState._notifEnabled = notifEnabled;
                        dbState._utcTablesUpdated = DateTime.UtcNow;
                        
                        Debug.Trace("SqlCacheDependencyManagerPolling", "dbState:_pollExpt="+ dbState._pollExpt + 
                                "; _pollSqlError=" + dbState._pollSqlError + "; _notifEnabled=" + dbState._notifEnabled +
                                "; __utcTablesUpdated=" + dbState._utcTablesUpdated);
                    }

                    // Mark dbState as initialized by PollCallback for the first time.
                    // EnsureTableIsRegisteredAndPolled() depends on this.
                    if (dbState._init != true) {
                        dbState._init = true;
                    }

                    Interlocked.Decrement(ref s_activePolling);
                    
                    // Release the lock                
                    Interlocked.Exchange(ref dbState._rqInCallback, 0);
                }
            }
            catch { throw; }    // Prevent Exception Filter Security Issue (ASURT 122835)            
        }
 internal static void PollDatabaseForChanges(DatabaseNotifState dbState, bool fromTimer)
 {
     SqlDataReader reader = null;
     SqlConnection sqlConn = null;
     SqlCommand sqlCmd = null;
     CacheInternal cacheInternal = HttpRuntime.CacheInternal;
     bool flag = false;
     Exception exception = null;
     SqlException exception2 = null;
     if (s_shutdown)
     {
         return;
     }
     if (((dbState._refCount == 0) && fromTimer) && dbState._init)
     {
         return;
     }
     if (Interlocked.CompareExchange(ref dbState._rqInCallback, 1, 0) != 0)
     {
         int num2;
         if (fromTimer)
         {
             return;
         }
         HttpContext current = HttpContext.Current;
         if (current == null)
         {
             num2 = 30;
         }
         else
         {
             num2 = Math.Max(current.Timeout.Seconds / 3, 30);
         }
         DateTime time = DateTime.UtcNow.Add(new TimeSpan(0, 0, num2));
         do
         {
             if (Interlocked.CompareExchange(ref dbState._rqInCallback, 1, 0) == 0)
             {
                 goto Label_00EA;
             }
             Thread.Sleep(250);
             if (s_shutdown)
             {
                 return;
             }
         }
         while (Debugger.IsAttached || (DateTime.UtcNow <= time));
         throw new HttpException(System.Web.SR.GetString("Cant_connect_sql_cache_dep_database_polling", new object[] { dbState._database }));
     }
 Label_00EA:
     try
     {
         try
         {
             Interlocked.Increment(ref s_activePolling);
             dbState.GetConnection(out sqlConn, out sqlCmd);
             reader = sqlCmd.ExecuteReader();
             if (!s_shutdown)
             {
                 flag = true;
                 Hashtable hashtable = (Hashtable) dbState._tables.Clone();
                 while (reader.Read())
                 {
                     string table = reader.GetString(0);
                     int num = reader.GetInt32(1);
                     string moniterKey = GetMoniterKey(dbState._database, table);
                     object obj2 = cacheInternal[moniterKey];
                     if (obj2 == null)
                     {
                         cacheInternal.UtcAdd(moniterKey, num, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null);
                         dbState._tables.Add(table, null);
                     }
                     else if (num != ((int) obj2))
                     {
                         cacheInternal.UtcInsert(moniterKey, num, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null);
                     }
                     hashtable.Remove(table);
                 }
                 foreach (object obj3 in hashtable.Keys)
                 {
                     dbState._tables.Remove((string) obj3);
                     cacheInternal.Remove(GetMoniterKey(dbState._database, (string) obj3));
                 }
                 if (dbState._pollSqlError != 0)
                 {
                     dbState._pollSqlError = 0;
                 }
             }
         }
         catch (Exception exception3)
         {
             exception = exception3;
             exception2 = exception3 as SqlException;
             if (exception2 != null)
             {
                 dbState._pollSqlError = exception2.Number;
             }
             else
             {
                 dbState._pollSqlError = 0;
             }
         }
         finally
         {
             try
             {
                 if (reader != null)
                 {
                     reader.Close();
                 }
                 dbState.ReleaseConnection(ref sqlConn, ref sqlCmd, exception != null);
             }
             catch
             {
             }
             lock (dbState)
             {
                 dbState._pollExpt = exception;
                 if ((dbState._notifEnabled && !flag) && ((exception != null) && (dbState._pollSqlError == 0xafc)))
                 {
                     foreach (object obj4 in dbState._tables.Keys)
                     {
                         try
                         {
                             cacheInternal.Remove(GetMoniterKey(dbState._database, (string) obj4));
                         }
                         catch
                         {
                         }
                     }
                     dbState._tables.Clear();
                 }
                 dbState._notifEnabled = flag;
                 dbState._utcTablesUpdated = DateTime.UtcNow;
             }
             if (!dbState._init)
             {
                 dbState._init = true;
             }
             Interlocked.Decrement(ref s_activePolling);
             Interlocked.Exchange(ref dbState._rqInCallback, 0);
         }
     }
     catch
     {
         throw;
     }
 }
        internal static void PollDatabaseForChanges(DatabaseNotifState dbState, bool fromTimer)
        {
            SqlDataReader reader        = null;
            SqlConnection sqlConn       = null;
            SqlCommand    sqlCmd        = null;
            CacheInternal cacheInternal = HttpRuntime.CacheInternal;
            bool          flag          = false;
            Exception     exception     = null;
            SqlException  exception2    = null;

            if (s_shutdown)
            {
                return;
            }
            if (((dbState._refCount == 0) && fromTimer) && dbState._init)
            {
                return;
            }
            if (Interlocked.CompareExchange(ref dbState._rqInCallback, 1, 0) != 0)
            {
                int num2;
                if (fromTimer)
                {
                    return;
                }
                HttpContext current = HttpContext.Current;
                if (current == null)
                {
                    num2 = 30;
                }
                else
                {
                    num2 = Math.Max(current.Timeout.Seconds / 3, 30);
                }
                DateTime time = DateTime.UtcNow.Add(new TimeSpan(0, 0, num2));
                do
                {
                    if (Interlocked.CompareExchange(ref dbState._rqInCallback, 1, 0) == 0)
                    {
                        goto Label_00EA;
                    }
                    Thread.Sleep(250);
                    if (s_shutdown)
                    {
                        return;
                    }
                }while (Debugger.IsAttached || (DateTime.UtcNow <= time));
                throw new HttpException(System.Web.SR.GetString("Cant_connect_sql_cache_dep_database_polling", new object[] { dbState._database }));
            }
Label_00EA:
            try
            {
                try
                {
                    Interlocked.Increment(ref s_activePolling);
                    dbState.GetConnection(out sqlConn, out sqlCmd);
                    reader = sqlCmd.ExecuteReader();
                    if (!s_shutdown)
                    {
                        flag = true;
                        Hashtable hashtable = (Hashtable)dbState._tables.Clone();
                        while (reader.Read())
                        {
                            string table      = reader.GetString(0);
                            int    num        = reader.GetInt32(1);
                            string moniterKey = GetMoniterKey(dbState._database, table);
                            object obj2       = cacheInternal[moniterKey];
                            if (obj2 == null)
                            {
                                cacheInternal.UtcAdd(moniterKey, num, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null);
                                dbState._tables.Add(table, null);
                            }
                            else if (num != ((int)obj2))
                            {
                                cacheInternal.UtcInsert(moniterKey, num, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null);
                            }
                            hashtable.Remove(table);
                        }
                        foreach (object obj3 in hashtable.Keys)
                        {
                            dbState._tables.Remove((string)obj3);
                            cacheInternal.Remove(GetMoniterKey(dbState._database, (string)obj3));
                        }
                        if (dbState._pollSqlError != 0)
                        {
                            dbState._pollSqlError = 0;
                        }
                    }
                }
                catch (Exception exception3)
                {
                    exception  = exception3;
                    exception2 = exception3 as SqlException;
                    if (exception2 != null)
                    {
                        dbState._pollSqlError = exception2.Number;
                    }
                    else
                    {
                        dbState._pollSqlError = 0;
                    }
                }
                finally
                {
                    try
                    {
                        if (reader != null)
                        {
                            reader.Close();
                        }
                        dbState.ReleaseConnection(ref sqlConn, ref sqlCmd, exception != null);
                    }
                    catch
                    {
                    }
                    lock (dbState)
                    {
                        dbState._pollExpt = exception;
                        if ((dbState._notifEnabled && !flag) && ((exception != null) && (dbState._pollSqlError == 0xafc)))
                        {
                            foreach (object obj4 in dbState._tables.Keys)
                            {
                                try
                                {
                                    cacheInternal.Remove(GetMoniterKey(dbState._database, (string)obj4));
                                }
                                catch
                                {
                                }
                            }
                            dbState._tables.Clear();
                        }
                        dbState._notifEnabled     = flag;
                        dbState._utcTablesUpdated = DateTime.UtcNow;
                    }
                    if (!dbState._init)
                    {
                        dbState._init = true;
                    }
                    Interlocked.Decrement(ref s_activePolling);
                    Interlocked.Exchange(ref dbState._rqInCallback, 0);
                }
            }
            catch
            {
                throw;
            }
        }