// Events private void UnloadEventHandler(object sender, EventArgs e) { // Make non-blocking call to ProcessDispatcher to ThreadPool.QueueUserWorkItem to complete // stopping of all start calls in this AppDomain. For containers shared among various AppDomains, // this will just be a ref-count subtract. For non-shared containers, we will close the container // and clean-up. SqlDependencyProcessDispatcher dispatcher = SqlDependency.ProcessDispatcher; if (null != dispatcher) { dispatcher.QueueAppDomainUnloading(SqlDependency.AppDomainKey); } }
private void UnloadEventHandler(object sender, EventArgs e) { IntPtr ptr; Bid.NotificationsScopeEnter(out ptr, "<sc.SqlDependencyPerAppDomainDispatcher.UnloadEventHandler|DEP> %d#", this.ObjectID); try { SqlDependencyProcessDispatcher processDispatcher = SqlDependency.ProcessDispatcher; if (processDispatcher != null) { processDispatcher.QueueAppDomainUnloading(SqlDependency.AppDomainKey); } } finally { Bid.ScopeLeave(ref ptr); } }
// ------ // Events // ------ private void UnloadEventHandler(object sender, EventArgs e) { IntPtr hscp; Bid.NotificationsScopeEnter(out hscp, "<sc.SqlDependencyPerAppDomainDispatcher.UnloadEventHandler|DEP> %d#", ObjectID); try { // Make non-blocking call to ProcessDispatcher to ThreadPool.QueueUserWorkItem to complete // stopping of all start calls in this AppDomain. For containers shared among various AppDomains, // this will just be a ref-count subtract. For non-shared containers, we will close the container // and clean-up. SqlDependencyProcessDispatcher dispatcher = SqlDependency.ProcessDispatcher; if (null != dispatcher) { dispatcher.QueueAppDomainUnloading(SqlDependency.AppDomainKey); } } finally { Bid.ScopeLeave(ref hscp); } }
private static void ObtainProcessDispatcher() { byte[] data = SNINativeMethodWrapper.GetData(); if (data == null) { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> nativeStorage null, obtaining dispatcher AppDomain and creating ProcessDispatcher.\n"); _AppDomain defaultAppDomain = SNINativeMethodWrapper.GetDefaultAppDomain(); if (defaultAppDomain != null) { ObjectHandle handle = CreateProcessDispatcher(defaultAppDomain); if (handle != null) { SqlDependencyProcessDispatcher dispatcher = (SqlDependencyProcessDispatcher)handle.Unwrap(); if (dispatcher != null) { _processDispatcher = dispatcher.SingletonProcessDispatcher; ObjRef objRef = GetObjRef(_processDispatcher); BinaryFormatter formatter2 = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); GetSerializedObject(objRef, formatter2, stream); SNINativeMethodWrapper.SetData(stream.GetBuffer()); return; } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - ObjectHandle.Unwrap returned null!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyObtainProcessDispatcherFailureObjectHandle); } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - AppDomain.CreateInstance returned null!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureCreateInstance); } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - unable to obtain default AppDomain!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureAppDomain); } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> nativeStorage not null, obtaining existing dispatcher AppDomain and ProcessDispatcher.\n"); BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream2 = new MemoryStream(data); _processDispatcher = GetDeserializedObject(formatter, stream2); Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> processDispatcher obtained, ID: %d\n", _processDispatcher.ObjectID); }
private static void ObtainProcessDispatcher() { byte[] data = SNINativeMethodWrapper.GetData(); if (data == null) { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> nativeStorage null, obtaining dispatcher AppDomain and creating ProcessDispatcher.\n"); _AppDomain defaultAppDomain = SNINativeMethodWrapper.GetDefaultAppDomain(); if (defaultAppDomain != null) { ObjectHandle handle = CreateProcessDispatcher(defaultAppDomain); if (handle != null) { SqlDependencyProcessDispatcher dispatcher = (SqlDependencyProcessDispatcher) handle.Unwrap(); if (dispatcher != null) { _processDispatcher = dispatcher.SingletonProcessDispatcher; ObjRef objRef = GetObjRef(_processDispatcher); BinaryFormatter formatter2 = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); GetSerializedObject(objRef, formatter2, stream); SNINativeMethodWrapper.SetData(stream.GetBuffer()); return; } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - ObjectHandle.Unwrap returned null!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyObtainProcessDispatcherFailureObjectHandle); } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - AppDomain.CreateInstance returned null!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureCreateInstance); } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - unable to obtain default AppDomain!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureAppDomain); } Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> nativeStorage not null, obtaining existing dispatcher AppDomain and ProcessDispatcher.\n"); BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream2 = new MemoryStream(data); _processDispatcher = GetDeserializedObject(formatter, stream2); Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> processDispatcher obtained, ID: %d\n", _processDispatcher.ObjectID); }
private static ObjRef GetObjRef(SqlDependencyProcessDispatcher _processDispatcher) { return RemotingServices.Marshal(_processDispatcher); }
internal static bool Start(string connectionString, string queue, bool useDefaults) { if (string.IsNullOrEmpty(connectionString)) { if (null == connectionString) { throw ADP.ArgumentNull(nameof(connectionString)); } else { throw ADP.Argument(nameof(connectionString)); } } if (!useDefaults && string.IsNullOrEmpty(queue)) { // If specified but null or empty, use defaults. useDefaults = true; queue = null; // Force to null - for proper hashtable comparison for default case. } // End duplicate Start/Stop logic. bool errorOccurred = false; bool result = false; lock (s_startStopLock) { try { if (null == s_processDispatcher) { // Ensure _processDispatcher reference is present - inside lock. s_processDispatcher = SqlDependencyProcessDispatcher.SingletonProcessDispatcher; } if (useDefaults) { // Default listener. string server = null; DbConnectionPoolIdentity identity = null; string user = null; string database = null; string service = null; bool appDomainStart = false; RuntimeHelpers.PrepareConstrainedRegions(); try { // CER to ensure that if Start succeeds we add to hash completing setup. // Start using process wide default service/queue & database from connection string. result = s_processDispatcher.StartWithDefault( connectionString, out server, out identity, out user, out database, ref service, s_appDomainKey, SqlDependencyPerAppDomainDispatcher.SingletonInstance, out errorOccurred, out appDomainStart); } finally { if (appDomainStart && !errorOccurred) { // If success, add to hashtable. IdentityUserNamePair identityUser = new IdentityUserNamePair(identity, user); DatabaseServicePair databaseService = new DatabaseServicePair(database, service); if (!AddToServerUserHash(server, identityUser, databaseService)) { try { Stop(connectionString, queue, useDefaults, true); } catch (Exception e) { // Discard stop failure! if (!ADP.IsCatchableExceptionType(e)) { throw; } ADP.TraceExceptionWithoutRethrow(e); // Discard failure, but trace for now. } throw SQL.SqlDependencyDuplicateStart(); } } } } else { // Start with specified service/queue & database. result = s_processDispatcher.Start( connectionString, queue, s_appDomainKey, SqlDependencyPerAppDomainDispatcher.SingletonInstance); // No need to call AddToServerDatabaseHash since if not using default queue user is required // to provide options themselves. } } catch (Exception e) { if (!ADP.IsCatchableExceptionType(e)) { throw; } ADP.TraceExceptionWithoutRethrow(e); // Discard failure, but trace for now. throw; } } return(result); }
private static void ObtainProcessDispatcher() { byte[] nativeStorage = SNINativeMethodWrapper.GetData(); if (nativeStorage == null) { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> nativeStorage null, obtaining dispatcher AppDomain and creating ProcessDispatcher.\n"); #if DEBUG // Possibly expensive, limit to debug. Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> AppDomain.CurrentDomain.FriendlyName: %ls\n", AppDomain.CurrentDomain.FriendlyName); #endif _AppDomain masterDomain = SNINativeMethodWrapper.GetDefaultAppDomain(); if (null != masterDomain) { ObjectHandle handle = CreateProcessDispatcher(masterDomain); if (null != handle) { SqlDependencyProcessDispatcher dependency = (SqlDependencyProcessDispatcher) handle.Unwrap(); if (null != dependency) { _processDispatcher = dependency.SingletonProcessDispatcher; // Set to static instance. // Serialize and set in native. ObjRef objRef = GetObjRef(_processDispatcher); BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); GetSerializedObject(objRef, formatter, stream); SNINativeMethodWrapper.SetData(stream.GetBuffer()); // Native will be forced to synchronize and not overwrite. } else { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - ObjectHandle.Unwrap returned null!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyObtainProcessDispatcherFailureObjectHandle); } } else { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - AppDomain.CreateInstance returned null!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureCreateInstance); } } else { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP|ERR> ERROR - unable to obtain default AppDomain!\n"); throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureAppDomain); } } else { Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> nativeStorage not null, obtaining existing dispatcher AppDomain and ProcessDispatcher.\n"); #if DEBUG // Possibly expensive, limit to debug. Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> AppDomain.CurrentDomain.FriendlyName: %ls\n", AppDomain.CurrentDomain.FriendlyName); #endif BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream = new MemoryStream(nativeStorage); _processDispatcher = GetDeserializedObject(formatter, stream); // Deserialize and set for appdomain. Bid.NotificationsTrace("<sc.SqlDependency.ObtainProcessDispatcher|DEP> processDispatcher obtained, ID: %d\n", _processDispatcher.ObjectID); } }
private static ObjRef GetObjRef(SqlDependencyProcessDispatcher _processDispatcher) { return(RemotingServices.Marshal(_processDispatcher)); }
internal SqlConnectionContainer(SqlDependencyProcessDispatcher.SqlConnectionContainerHashHelper hashHelper, string appDomainKey, bool useDefaults) { IntPtr ptr; this._defaultWaitforTimeout = 0xea60; this._objectID = Interlocked.Increment(ref _objectTypeCount); Bid.NotificationsScopeEnter(out ptr, "<sc.SqlConnectionContainer|DEP> %d#, queue: '%ls'", this.ObjectID, hashHelper.Queue); bool flag = false; try { this._hashHelper = hashHelper; string str = null; if (useDefaults) { str = Guid.NewGuid().ToString(); this._queue = "SqlQueryNotificationService-" + str; this._hashHelper.ConnectionStringBuilder.ApplicationName = this._queue; } else { this._queue = this._hashHelper.Queue; } this._con = new SqlConnection(this._hashHelper.ConnectionStringBuilder.ConnectionString); ((SqlConnectionString) this._con.ConnectionOptions).CreatePermissionSet().Assert(); this._con.Open(); this._cachedServer = this._con.DataSource; if (!this._con.IsYukonOrNewer) { throw SQL.NotificationsRequireYukon(); } if (hashHelper.Identity != null) { this._windowsIdentity = DbConnectionPoolIdentity.GetCurrentWindowsIdentity(); } this._escapedQueueName = SqlConnection.FixupDatabaseTransactionName(this._queue); this._appDomainKeyHash = new Dictionary<string, int>(); this._com = new SqlCommand(); this._com.Connection = this._con; this._com.CommandText = "select is_broker_enabled from sys.databases where database_id=db_id()"; if (!((bool) this._com.ExecuteScalar())) { throw SQL.SqlDependencyDatabaseBrokerDisabled(); } this._conversationGuidParam = new SqlParameter("@p1", SqlDbType.UniqueIdentifier); this._timeoutParam = new SqlParameter("@p2", SqlDbType.Int); this._timeoutParam.Value = 0; this._com.Parameters.Add(this._timeoutParam); flag = true; this._receiveQuery = "WAITFOR(RECEIVE TOP (1) message_type_name, conversation_handle, cast(message_body AS XML) as message_body from " + this._escapedQueueName + "), TIMEOUT @p2;"; if (useDefaults) { this._sprocName = SqlConnection.FixupDatabaseTransactionName("SqlQueryNotificationStoredProcedure-" + str); this.CreateQueueAndService(false); } else { this._com.CommandText = this._receiveQuery; this._endConversationQuery = "END CONVERSATION @p1; "; this._concatQuery = this._endConversationQuery + this._receiveQuery; } bool appDomainStart = false; this.IncrementStartCount(appDomainKey, out appDomainStart); this.SynchronouslyQueryServiceBrokerQueue(); this._timeoutParam.Value = this._defaultWaitforTimeout; this.AsynchronouslyQueryServiceBrokerQueue(); } catch (Exception exception) { if (!ADP.IsCatchableExceptionType(exception)) { throw; } ADP.TraceExceptionWithoutRethrow(exception); if (flag) { this.TearDownAndDispose(); } else { if (this._com != null) { this._com.Dispose(); this._com = null; } if (this._con != null) { this._con.Dispose(); this._con = null; } } throw; } finally { Bid.ScopeLeave(ref ptr); } }