/// <summary> /// Formats the client list array for output in the sysadm dialog for selection of a client id /// </summary> /// <returns>Formatted client list for sysadm dialog. /// </returns> public String FormatClientListSysadm(Boolean AListDisconnectedClients) { return(TClientManager.FormatClientListSysadm(AListDisconnectedClients)); }
/// <summary> /// Queues a ClientTask for a certain Client. /// </summary> /// <param name="AClientID">Server-assigned ID of the Client</param> /// <param name="ATaskGroup">Group of the Task</param> /// <param name="ATaskCode">Code of the Task</param> /// <param name="ATaskParameter1">Parameter #1 for the Task (depending on the TaskGroup /// this can be left empty)</param> /// <param name="ATaskParameter2">Parameter #2 for the Task (depending on the TaskGroup /// this can be left empty)</param> /// <param name="ATaskParameter3">Parameter #3 for the Task (depending on the TaskGroup /// this can be left empty)</param> /// <param name="ATaskParameter4">Parameter #4 for the Task (depending on the TaskGroup /// this can be left empty)</param> /// <param name="ATaskPriority">Priority of the Task</param> /// <returns>true if ClientTask was queued, otherwise false.</returns> public bool QueueClientTask(System.Int16 AClientID, String ATaskGroup, String ATaskCode, object ATaskParameter1, object ATaskParameter2, object ATaskParameter3, object ATaskParameter4, System.Int16 ATaskPriority) { return(TClientManager.QueueClientTask(AClientID, ATaskGroup, ATaskCode, ATaskParameter1, ATaskParameter2, ATaskParameter3, ATaskParameter4, ATaskPriority) >= 0); }
/// <summary> /// Requests disconnection of a certain Client from the Petra Server. /// /// </summary> /// <param name="AClientID">Server-assigned ID of the Client</param> /// <param name="ACantDisconnectReason">Reason why the Client cannot be disconnected</param> /// <returns>true if disconnection succeeded, otherwise false. /// </returns> public bool DisconnectClient(System.Int16 AClientID, out String ACantDisconnectReason) { return(TClientManager.ServerDisconnectClient(AClientID, "Client disconnection requested by Adminstrator!", out ACantDisconnectReason)); }
/// <summary> /// Initialises variables. /// /// </summary> /// <returns>void</returns> public TClientManager() { FClientManagerCallForwarder = new TClientManagerCallForwarder(this); UClientObjects = SortedList.Synchronized(new SortedList()); // Console.WriteLine('UClientObjects.IsSynchronized: ' + UClientObjects.IsSynchronized.ToString); FStartTime = DateTime.Now; UConnectClientMonitor = new System.Object(); UClientManagerObj = this; }
/// <summary> /// todoComment /// </summary> public void StartClientDisconnection() { const Int32 UNLOAD_RETRIES = 20; Int32 UnloadExceptionCount; String ClientInfo; Boolean DBConnectionAlreadyClosed; Boolean UnloadFinished; DBConnectionAlreadyClosed = false; UnloadExceptionCount = 0; try { ClientInfo = "'" + FAppDomainEntry.FClientName + "' (ClientID: " + FAppDomainEntry.FClientID.ToString() + ")"; if (TLogging.DL >= 4) { Console.WriteLine(TClientManager.FormatClientList(false)); Console.WriteLine(TClientManager.FormatClientList(true)); } if (TLogging.DL >= 4) { TLogging.Log("Disconnecting Client " + ClientInfo + " (Reason: " + FReason + ")...", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Disconnecting Client " + ClientInfo + " (Reason: " + FReason + ")...", TLoggingType.ToLogfile); } FAppDomainEntry.FClientDisconnectionStartTime = DateTime.Now; FAppDomainEntry.FAppDomainStatus = TAppDomainStatus.adsDisconnectingDBClosing; try { if (TLogging.DL >= 4) { TLogging.Log("Closing Client DB Connection... [Client " + ClientInfo + "]", TLoggingType.ToConsole | TLoggingType.ToLogfile); } try { FAppDomainEntry.ClientAppDomainConnection.CloseDBConnection(); } catch (System.ArgumentNullException) { // don't do anything here: this Exception only indicates that the // DB connection was already closed. DBConnectionAlreadyClosed = true; } catch (Exception) { // make sure any other Exception is going to be handled throw; } if (!DBConnectionAlreadyClosed) { if (TLogging.DL >= 4) { TLogging.Log("Closed Client DB Connection. [Client " + ClientInfo + "]", TLoggingType.ToConsole | TLoggingType.ToLogfile); } } else { if (TLogging.DL >= 4) { TLogging.Log("Client DB Connection was already closed. [Client " + ClientInfo + "]", TLoggingType.ToConsole | TLoggingType.ToLogfile); } } } catch (Exception exp) { TLogging.Log( "Error closing Database connection on Client disconnection!" + " [Client " + ClientInfo + "]" + "Exception: " + exp.ToString()); } if (TLogging.DL >= 5) { TLogging.Log(" Before calling ClientAppDomainConnection.StopClientAppDomain... [Client " + ClientInfo + ']', TLoggingType.ToConsole | TLoggingType.ToLogfile); } FAppDomainEntry.ClientAppDomainConnection.StopClientAppDomain(); if (TLogging.DL >= 5) { TLogging.Log(" After calling ClientAppDomainConnection.StopClientAppDomain... [Client " + ClientInfo + ']', TLoggingType.ToConsole | TLoggingType.ToLogfile); } FAppDomainEntry.FAppDomainStatus = TAppDomainStatus.adsDisconnectingAppDomainUnloading; UnloadFinished = false; while (!UnloadFinished) { try { Retry: // used only for repeating Unload when an Exception happened if (Monitor.TryEnter(UAppDomainUnloadMonitor, 250)) { /* * Try to unload the AppDomain. If an Exception occurs, retries are made * after a delay - until a maximum of retries is reached. */ if (TLogging.DL >= 5) { Console.WriteLine( " Unloading AppDomain '" + FAppDomainEntry.ClientAppDomainConnection.AppDomainName + "' [Client " + ClientInfo + "]"); } try { if (TLogging.DL >= 4) { TLogging.Log("Unloading Client Session (AppDomain)..." + "' [Client " + ClientInfo + "]", TLoggingType.ToConsole | TLoggingType.ToLogfile); } // Note for developers: uncomment the following code to see that the retrying of Unload really works in case Exceptions are thrown,,, // if (UnloadExceptionCount < 4) // { // raise Exception.Create(); // } // Unload the AppDomain FAppDomainEntry.ClientAppDomainConnection.Unload(); // Everything went fine! if (TLogging.DL >= 4) { TLogging.Log("Unloaded Client Session (AppDomain)." + "' [Client " + ClientInfo + "]", TLoggingType.ToConsole | TLoggingType.ToLogfile); } UnloadExceptionCount = 0; FAppDomainEntry.FClientAppDomainConnection = null; FAppDomainEntry.FClientDisconnectionFinishedTime = DateTime.Now; FAppDomainEntry.FAppDomainStatus = TAppDomainStatus.adsStopped; if (TLogging.DL >= 5) { Console.WriteLine(" AppDomain unloaded [Client " + ClientInfo + "]"); } } catch (Exception UnloadException) { // Something went wrong during Unload; log this, wait a bit and // try again! UnloadExceptionCount = UnloadExceptionCount + 1; TLogging.Log( "Error unloading Client Session (AppDomain) [Client " + ClientInfo + "] on Client disconnection (try #" + UnloadExceptionCount.ToString() + ")! " + "Exception: " + UnloadException.ToString()); Monitor.PulseAll(UAppDomainUnloadMonitor); Monitor.Exit(UAppDomainUnloadMonitor); Thread.Sleep(UnloadExceptionCount * 1000); } if ((UnloadExceptionCount != 0) && (UnloadExceptionCount < UNLOAD_RETRIES)) { goto Retry; } if (TLogging.DL >= 5) { Console.WriteLine(" AppDomain unloading finished [Client " + ClientInfo + ']'); } // Logging: was Unload successful? if (FAppDomainEntry.FAppDomainStatus == TAppDomainStatus.adsStopped) { if (TLogging.DL >= 4) { TLogging.Log( "Client " + ClientInfo + " has been disconnected (took " + FAppDomainEntry.FClientDisconnectionFinishedTime.Subtract( FAppDomainEntry.FClientDisconnectionStartTime).TotalSeconds.ToString() + " sec).", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client " + ClientInfo + " has been disconnected.", TLoggingType.ToLogfile); } } else { if (TLogging.DL >= 4) { TLogging.Log("Client " + ClientInfo + " could not be disconnected!", TLoggingType.ToConsole | TLoggingType.ToLogfile); } else { TLogging.Log("Client " + ClientInfo + " could not be disconnected!", TLoggingType.ToLogfile); } } UnloadFinished = true; // Notify any other waiting Threads that they can proceed with the // Unloading of their AppDomain try { Monitor.PulseAll(UAppDomainUnloadMonitor); } catch (System.Threading.SynchronizationLockException) { if (UnloadExceptionCount == UNLOAD_RETRIES) { } // ignore this Exception if the amount of retries is reached // the Monitor is already Exited in this case else { throw; } } catch (Exception) { throw; } } else { if (TLogging.DL >= 4) { TLogging.Log( "Client disconnection Thread is blocked by another client disconnection thread. Waiting a bit... (ClientID: " + AppDomainEntry.FClientID.ToString() + ")...", TLoggingType.ToConsole | TLoggingType.ToLogfile); } Thread.Sleep(2000); if (TLogging.DL >= 4) { TLogging.Log( "Trying to continue Client disconnection after Thread was blocked by another client disconnection thread..." + "' (ClientID: " + AppDomainEntry.FClientID.ToString() + ")...", TLoggingType.ToConsole | TLoggingType.ToLogfile); } } } finally { Monitor.Exit(UAppDomainUnloadMonitor); } } } catch (Exception Exp) { TLogging.Log( "StartClientDisconnection for ClientID: " + FClientID.ToString() + ": Exception occured: " + Exp.ToString(), TLoggingType.ToConsole | TLoggingType.ToLogfile); } }
/// <summary> /// Initialize the Petra server and connect to the database /// </summary> /// <param name="AConfigName">just provide the server config file, plus AutoLogin and AutoLoginPasswd</param> public static TServerManager Connect(string AConfigName) { if (File.Exists(AConfigName)) { new TAppSettingsManager(AConfigName); } else { new TAppSettingsManager(); } new TLogging(TAppSettingsManager.GetValue("Server.LogFile")); CommonNUnitFunctions.InitRootPath(); Catalog.Init(); TServerManager ServerManager = new TServerManager(); DBAccess.GDBAccessObj = new TDataBase(); DBAccess.GDBAccessObj.EstablishDBConnection(TSrvSetting.RDMBSType, TSrvSetting.PostgreSQLServer, TSrvSetting.PostgreSQLServerPort, TSrvSetting.PostgreSQLDatabaseName, TSrvSetting.DBUsername, TSrvSetting.DBPassword, ""); bool SystemEnabled; int ProcessID; TPetraPrincipal UserInfo = (TPetraPrincipal)TClientManager.PerformLoginChecks(TAppSettingsManager.GetValue("AutoLogin").ToUpper(), TAppSettingsManager.GetValue("AutoLoginPasswd"), "NUNITTEST", "127.0.0.1", out ProcessID, out SystemEnabled); if (FDomain != null) { FDomain.StopClientAppDomain(); } TClientManager ClientManager = new TClientManager(); DomainManager.UClientManagerCallForwarderRef = new TClientManagerCallForwarder(ClientManager); // do the same as in Ict.Petra.Server.App.Main.TRemoteLoader.LoadDomainManagerAssembly FDomain = new TClientDomainManager("0", TClientServerConnectionType.csctLocal, DomainManager.UClientManagerCallForwarderRef, new TSystemDefaultsCache(), new TCacheableTablesManager(null), UserInfo); FDomain.InitAppDomain(TSrvSetting.ServerSettings); new TCallForwarding(); // we don't need to establish the database connection anymore // FDomain.EstablishDBConnection(); return ServerManager; }