// For Non-SQL9 SQL servers, we create a dependency based on an internal cached item.        

        public SqlCacheDependency(string databaseEntryName, string tableName) 
        :base(0, null, new string[1] {GetDependKey(databaseEntryName, tableName)})
        {
            Debug.Trace("SqlCacheDependency", 
                            "Depend on key=" + GetDependKey(databaseEntryName, tableName) + "; value=" +
                            HttpRuntime.CacheInternal[GetDependKey(databaseEntryName, tableName)]);

            // Permission checking is done in GetDependKey()

            _sql7DatabaseState = SqlCacheDependencyManager.AddRef(databaseEntryName);
            _sql7DepInfo._database = databaseEntryName;
            _sql7DepInfo._table = tableName;

            object o = HttpRuntime.CacheInternal[GetDependKey(databaseEntryName, tableName)];
            if (o == null) {
                // If the cache entry can't be found, this cache dependency will be set to CHANGED already.
                _sql7ChangeId = -1;
            }
            else {
                // Note that if the value in the cache changed between the base ctor and here, even though
                // we get a wrong unqiue Id, but it's okay because that change will cause the CacheDependency's
                // state to become CHANGED and any cache operation using this CacheDependency will fail anyway.
                _sql7ChangeId = (int)o;
            }

            // The ctor of every class derived from CacheDependency must call this.
            FinishInit();

            InitUniqueID();
        }
        internal static DatabaseNotifState AddRef(string database)
        {
            DatabaseNotifState state = (DatabaseNotifState)s_DatabaseNotifStates[database];

            Interlocked.Increment(ref state._refCount);
            return(state);
        }
        internal static void InitPolling(string database)
        {
            SqlCacheDependencySection sqlCacheDependency = RuntimeConfig.GetAppConfig().SqlCacheDependency;

            if (!sqlCacheDependency.Enabled)
            {
                throw new ConfigurationErrorsException(System.Web.SR.GetString("Polling_not_enabled_for_sql_cache"), sqlCacheDependency.ElementInformation.Properties["enabled"].Source, sqlCacheDependency.ElementInformation.Properties["enabled"].LineNumber);
            }
            SqlCacheDependencyDatabase databaseConfig = GetDatabaseConfig(database);

            if (databaseConfig.PollTime == 0)
            {
                throw new ConfigurationErrorsException(System.Web.SR.GetString("Polltime_zero_for_database_sql_cache", new object[] { database }), databaseConfig.ElementInformation.Properties["pollTime"].Source, databaseConfig.ElementInformation.Properties["pollTime"].LineNumber);
            }
            if (!s_DatabaseNotifStates.ContainsKey(database))
            {
                string connection = SqlConnectionHelper.GetConnectionString(databaseConfig.ConnectionStringName, true, true);
                if ((connection == null) || (connection.Length < 1))
                {
                    throw new ConfigurationErrorsException(System.Web.SR.GetString("Connection_string_not_found", new object[] { databaseConfig.ConnectionStringName }), databaseConfig.ElementInformation.Properties["connectionStringName"].Source, databaseConfig.ElementInformation.Properties["connectionStringName"].LineNumber);
                }
                lock (s_DatabaseNotifStates)
                {
                    if (!s_DatabaseNotifStates.ContainsKey(database))
                    {
                        DatabaseNotifState state;
                        state = new DatabaseNotifState(database, connection, databaseConfig.PollTime)
                        {
                            _timer = new Timer(s_timerCallback, state, 0, databaseConfig.PollTime)
                        };
                        s_DatabaseNotifStates.Add(database, state);
                    }
                }
            }
        }
 internal static void UpdateAllDatabaseNotifState()
 {
     lock (s_DatabaseNotifStates)
     {
         foreach (DictionaryEntry entry in s_DatabaseNotifStates)
         {
             DatabaseNotifState state = (DatabaseNotifState)entry.Value;
             if (state._init)
             {
                 UpdateDatabaseNotifState((string)entry.Key);
             }
         }
     }
 }
 public SqlCacheDependency(string databaseEntryName, string tableName) : base(0, null, new string[] { GetDependKey(databaseEntryName, tableName) })
 {
     this._sql7DatabaseState = SqlCacheDependencyManager.AddRef(databaseEntryName);
     this._sql7DepInfo._database = databaseEntryName;
     this._sql7DepInfo._table = tableName;
     object obj2 = HttpRuntime.CacheInternal[GetDependKey(databaseEntryName, tableName)];
     if (obj2 == null)
     {
         this._sql7ChangeId = -1;
     }
     else
     {
         this._sql7ChangeId = (int) obj2;
     }
     base.FinishInit();
     this.InitUniqueID();
 }
Exemple #6
0
        public SqlCacheDependency(string databaseEntryName, string tableName) : base(0, null, new string[] { GetDependKey(databaseEntryName, tableName) })
        {
            this._sql7DatabaseState     = SqlCacheDependencyManager.AddRef(databaseEntryName);
            this._sql7DepInfo._database = databaseEntryName;
            this._sql7DepInfo._table    = tableName;
            object obj2 = HttpRuntime.CacheInternal[GetDependKey(databaseEntryName, tableName)];

            if (obj2 == null)
            {
                this._sql7ChangeId = -1;
            }
            else
            {
                this._sql7ChangeId = (int)obj2;
            }
            base.FinishInit();
            this.InitUniqueID();
        }
 internal static void Release(DatabaseNotifState dbState)
 {
     Interlocked.Decrement(ref dbState._refCount);
 }
 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 InitPolling(string database)
 {
     SqlCacheDependencySection sqlCacheDependency = RuntimeConfig.GetAppConfig().SqlCacheDependency;
     if (!sqlCacheDependency.Enabled)
     {
         throw new ConfigurationErrorsException(System.Web.SR.GetString("Polling_not_enabled_for_sql_cache"), sqlCacheDependency.ElementInformation.Properties["enabled"].Source, sqlCacheDependency.ElementInformation.Properties["enabled"].LineNumber);
     }
     SqlCacheDependencyDatabase databaseConfig = GetDatabaseConfig(database);
     if (databaseConfig.PollTime == 0)
     {
         throw new ConfigurationErrorsException(System.Web.SR.GetString("Polltime_zero_for_database_sql_cache", new object[] { database }), databaseConfig.ElementInformation.Properties["pollTime"].Source, databaseConfig.ElementInformation.Properties["pollTime"].LineNumber);
     }
     if (!s_DatabaseNotifStates.ContainsKey(database))
     {
         string connection = SqlConnectionHelper.GetConnectionString(databaseConfig.ConnectionStringName, true, true);
         if ((connection == null) || (connection.Length < 1))
         {
             throw new ConfigurationErrorsException(System.Web.SR.GetString("Connection_string_not_found", new object[] { databaseConfig.ConnectionStringName }), databaseConfig.ElementInformation.Properties["connectionStringName"].Source, databaseConfig.ElementInformation.Properties["connectionStringName"].LineNumber);
         }
         lock (s_DatabaseNotifStates)
         {
             if (!s_DatabaseNotifStates.ContainsKey(database))
             {
                 DatabaseNotifState state;
                 state = new DatabaseNotifState(database, connection, databaseConfig.PollTime) {
                     _timer = new Timer(s_timerCallback, state, 0, databaseConfig.PollTime)
                 };
                 s_DatabaseNotifStates.Add(database, state);
             }
         }
     }
 }
        // 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)            
        }
        // Initialize polling for a database.  It will:
        // 1. Create the DatabaseNotifState that holds the polling status about this database.
        // 2. Create the timer to poll.
        internal static void InitPolling(string database) {
            SqlCacheDependencySection config = RuntimeConfig.GetAppConfig().SqlCacheDependency;;
            SqlCacheDependencyDatabase  sqlDepDB;
            string connectionString;

            Debug.Trace("SqlCacheDependencyManager", 
                                "InitPolling is called.  Database=" + database);

            // Return if polling isn't even enabled.            
            if (!config.Enabled) {
                throw new ConfigurationErrorsException(
                    SR.GetString(SR.Polling_not_enabled_for_sql_cache),
                    config.ElementInformation.Properties["enabled"].Source, config.ElementInformation.Properties["enabled"].LineNumber);
            }

            // Return if the polltime is zero.  It means polling is disabled for this database.
            sqlDepDB = GetDatabaseConfig(database);
            if (sqlDepDB.PollTime == 0) {
                throw new ConfigurationErrorsException(
                    SR.GetString(SR.Polltime_zero_for_database_sql_cache, database),
                    sqlDepDB.ElementInformation.Properties["pollTime"].Source, sqlDepDB.ElementInformation.Properties["pollTime"].LineNumber);
            }

            if (s_DatabaseNotifStates.ContainsKey(database)) {
                // Someone has already started the timer for this database.
                Debug.Trace("SqlCacheDependencyManager", 
                                "InitPolling: Timer already started for " + database);

                return;
            }

            connectionString = SqlConnectionHelper.GetConnectionString(sqlDepDB.ConnectionStringName, true, true);
            if (connectionString == null || connectionString.Length < 1) {
                throw new ConfigurationErrorsException(
                    SR.GetString(SR.Connection_string_not_found, sqlDepDB.ConnectionStringName),
                    sqlDepDB.ElementInformation.Properties["connectionStringName"].Source, sqlDepDB.ElementInformation.Properties["connectionStringName"].LineNumber);
            }

            lock(s_DatabaseNotifStates) {
                DatabaseNotifState   state;

                if (s_DatabaseNotifStates.ContainsKey(database)) {
                    // Someone has already started the timer for this database.
                    Debug.Trace("SqlCacheDependencyManager", 
                                "InitPolling: Timer already started for " + database);

                    return;
                }

                Debug.Trace("SqlCacheDependencyManager", 
                                "InitPolling: Creating timer for " + database);

                state = new DatabaseNotifState(database, connectionString, sqlDepDB.PollTime);
                state._timer = new Timer(s_timerCallback, state, 0 /* dueTime */, sqlDepDB.PollTime /* period */);

                s_DatabaseNotifStates.Add(database, state);
            }
        }
        internal static void Release(DatabaseNotifState dbState) {
#if DBG
            int res = 
#endif            
            Interlocked.Decrement(ref dbState._refCount);
#if DBG
            Debug.Trace("SqlCacheDependencyManager", "Release called for " + dbState._database + "; res=" + res);
            Debug.Assert(res >= 0, "Release result for " + dbState._database + " must be >= 0");
#endif
        }
        internal static void EnsureTableIsRegisteredAndPolled(string database, string table)
        {
            DateTime  time2;
            bool      flag2;
            Exception exception;
            int       num2;
            bool      flag = false;

            if (HttpRuntime.CacheInternal[GetMoniterKey(database, table)] != null)
            {
                return;
            }
            InitPolling(database);
            DatabaseNotifState state = (DatabaseNotifState)s_DatabaseNotifStates[database];

            if (!state._init)
            {
                int         num;
                HttpContext current = HttpContext.Current;
                if (current == null)
                {
                    num = 30;
                }
                else
                {
                    num = Math.Max(current.Timeout.Seconds / 3, 30);
                }
                DateTime time = DateTime.UtcNow.Add(new TimeSpan(0, 0, num));
                do
                {
                    if (state._init)
                    {
                        goto Label_00BD;
                    }
                    Thread.Sleep(250);
                }while (Debugger.IsAttached || (DateTime.UtcNow <= time));
                throw new HttpException(System.Web.SR.GetString("Cant_connect_sql_cache_dep_database_polling", new object[] { database }));
            }
Label_00BD:
            num2 = 0;
            lock (state)
            {
                exception = state._pollExpt;
                if (exception != null)
                {
                    num2 = state._pollSqlError;
                }
                time2 = state._utcTablesUpdated;
                flag2 = state._notifEnabled;
            }
            if (((exception == null) && flag2) && state._tables.ContainsKey(table))
            {
                return;
            }
            if (flag || ((DateTime.UtcNow - time2) < OneSec))
            {
                string str;
                if (num2 == 0xafc)
                {
                    exception = null;
                }
                if (exception == null)
                {
                    if (!flag2)
                    {
                        throw new DatabaseNotEnabledForNotificationException(System.Web.SR.GetString("Database_not_enabled_for_notification", new object[] { database }));
                    }
                    throw new TableNotEnabledForNotificationException(System.Web.SR.GetString("Table_not_enabled_for_notification", new object[] { table, database }));
                }
                switch (num2)
                {
                case 0xe5:
                case 0x106:
                    str = "Permission_denied_database_polling";
                    break;

                default:
                    str = "Cant_connect_sql_cache_dep_database_polling";
                    break;
                }
                HttpException e = new HttpException(System.Web.SR.GetString(str, new object[] { database }), exception);
                e.SetFormatter(new UseLastUnhandledErrorFormatter(e));
                throw e;
            }
            UpdateDatabaseNotifState(database);
            flag = true;
            goto Label_00BD;
        }
 internal static void Release(DatabaseNotifState dbState)
 {
     Interlocked.Decrement(ref dbState._refCount);
 }
        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;
            }
        }