/// <summary> /// Mueve al cliente de la lista de inicio a la de trabajo. Notifica que se ha comenzado /// a monitorear al cliente. /// </summary> /// <param name="client">Referencia al objeto ClientData a mover.</param> private void ClientMoveToWorkList(ClientData client) { client.Status = ClientStatus.Operacional; //client.RestartCount = 0; client.RestartCountVolatil = 0; lock (_startList) { if (_startList.Contains(client)) { _startList.Remove(client); } } lock (_workList) { if (!_workList.Contains(client)) { _workList.Add(client); } } MessageBus.Send(new RequestSendEmail(EMessageAction.Operational, DateTime.Now, client)); Builder.Output(string.Format(ClassName + ": Cliente {0} movido a cola de Trabajo.", client.Name), TraceEventType.Verbose); }
/// <summary> /// Detecta demoras en la respuesta del cliente, despues de haber sido reiniciado. Si demora mas de un minuto /// (valor configurable) en enviar heartbeats se elimina de la lista de recuperacion (_recoverList) /// y se coloca en la lista de detenidos (_timeOutList) /// El tiempo a tener en cuenta se lee de la propiedad EnterTime, que se actualiza cuando se recibe /// heartbeat del cliente. /// </summary> private void CheckRecoverTimeout() { TimeSpan dif, timeout; List <ClientData> buffer = new List <ClientData>(_recoverList); foreach (var client in buffer) { dif = DateTime.Now.Subtract(client.EnterTime); timeout = TimeSpan.FromSeconds(_systemTimeout); if (dif > timeout) { client.Status = ClientStatus.Atrasado; // remove from _recoverList lock (_recoverList) { _recoverList.Remove(client); } // add to _timeOutList lock (_timeOutList) { if (!_timeOutList.Contains(client)) { _timeOutList.Add(client); } } Builder.Output(string.Format(ClassName + ": Cliente: {0} sin iniciar reporte despues de reiniciado, se mueve a cola de Detenido.", client.Name), TraceEventType.Warning); } } }
/// <summary> /// Detecta clientes reiniciados varias veces que no envian hearbeat. Si se ha reiniciado /// mas del limite configurado y sigue en la lista de recuperacion (_recoverList) se declara fuera de control. /// De lo contrario oscilaria indefinidamente entre _recoverList y _timeOutList. /// </summary> private void CheckRecoverDead() { TimeSpan dif, timeout; List <ClientData> buffer = new List <ClientData>(_recoverList); foreach (var client in buffer) { dif = DateTime.Now.Subtract(client.EnterTime); timeout = TimeSpan.FromSeconds(_systemTimeout); if ((dif > timeout) && (client.RestartCountVolatil == _restCount)) { client.Status = ClientStatus.Muerto; // remove from _recoverList lock (_recoverList) { _recoverList.Remove(client); } // add to _timeOutList lock (_deadList) { if (!_deadList.Contains(client)) { _deadList.Add(client); } } MessageBus.Send(new RequestSendEmail(EMessageAction.Dead, DateTime.Now, client)); Builder.Output(string.Format(ClassName + ": Cliente: {0} sin iniciar reporte despues de reiniciado, se mueve a cola de Detenido.", client.Name), TraceEventType.Critical); } } }
/// <summary> /// Termina una aplicacion. /// </summary> /// <param name="name">Nombre de la aplicacion a terminar.</param> private void KillProcessByName(string name) { Builder.Output(string.Format(ClassName + ": Terminando proceso: {0}.", name), TraceEventType.Information); Process[] pList; try { pList = Process.GetProcessesByName(name); } catch (Exception ex) { Log.WriteEntry(ClassName, "KillProcessByName", TraceEventType.Error, ex.Message); return; } foreach (var item in pList) { try { item.Kill(); while (!item.HasExited) { System.Threading.Thread.Sleep(10); } //Builder.Output(" Killed :" + name); Builder.Output(string.Format(ClassName + ": Proceso terminado: {0}.", item.ProcessName), TraceEventType.Information); } catch (Exception ex) { //System.Windows.Forms.MessageBox.Show(ex.Message); //throw; Log.WriteEntry(ClassName, "KillProcessByName", TraceEventType.Error, ex.Message); } } }
static private bool ConfigurarComponentes() { try { Builder.Output("Creando componentes."); // Crear referencias _clientManager = new ClientManager(); _notifier = new Notifier(); _zyanServer = new ZyanServer(); Builder.Output("Configurando componentes."); // ClientManager -> all Config MessageBus.Register <SendSystemConfig>(_clientManager.ReceiveSystemConfig); MessageBus.Register <SendClientConfig>(_clientManager.ReceiveClientConfig); // Notifier y ZyanServer -> system config MessageBus.Register <SendSystemConfig>(_notifier.ReceiveSystemConfig); MessageBus.Register <SendSystemConfig>(_zyanServer.ReceiveSystemConfig); // Enviando config MessageBus.Send(new SendClientConfig(_dbHandler.ClientList)); MessageBus.Send(new SendSystemConfig(_dbHandler.SystemData)); // Pausa para que los request handlers de los componentes terminen System.Threading.Thread.Sleep(100); return(true); } catch (Exception ex) { Builder.Output(string.Format("{0}.ConfigurarComponentes: ocurrio una excepcion: {1}", ClassName, ex.Message), System.Diagnostics.TraceEventType.Error); return(false); } }
internal bool IniciarServicio() { try { Builder.Output("Starting Monitor"); // Crear todo Build(); // Registrar Mensajes Mover al final RegisterMessages(); StartModules(); // Iniciar UDP server para recibir datos de clientes MessageBus.Send(new RequestStartUdpServer()); return(true); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); throw; } }
private void SendMail(EMessageAction action, EMessageStyle style, string name, DateTime date) { PlainTextMessage mess = new PlainTextMessage(action, style, name, date); HTMLMessage htmmess = new HTMLMessage(action, style, name, date); MailMessage mailMessage = new MailMessage(); // Direciones mailMessage.From = new MailAddress(_source); mailMessage.To.Add(_destination); // Asunto mailMessage.Subject = mess.Subject; // Cuerpo en texto plano mailMessage.Body = mess.Body; // Add HTML View AlternateView altHtml = AlternateView.CreateAlternateViewFromString(htmmess.Body, null, "text/html"); mailMessage.AlternateViews.Add(altHtml); try { EnviaEmail(mailMessage); } catch (Exception ex) { Builder.Output(string.Format("{0}.SendMail: Ocurrió una excepción: {1}", ClassName, ex.Message), TraceEventType.Error); throw ex; } }
static private void ClientManagerStopOK(ReplyStop reply) { Builder.Output("Confirmada detencion de ClientManager."); MessageBus.Remove <RequestStop>(_clientManager.Stop); MessageBus.Remove <ReplyStop>(ClientManagerStopOK); _areEsperaOperacion.Set(); }
static private void CargarTodosEjecutarConsole() { // instanciar aqui _messageOutput = new ConsoleOutput(OutputVerbose, true); Builder.Output("Ejecutando servicio en modo consola."); if (!ConfigurarComponentes()) { return; } if (!IniciarComponentes()) { return; } if (!RegistrarMensajes()) { return; } NotificarInicioSistema(); Builder.Output("Simulando ejecucion ininterrumpida del servicio. Parada en Console.ReadLine... "); Console.ReadLine(); DetenerComponentes(); }
static private void NotifierStopOK(ReplyStop reply) { Builder.Output("Confirmada detencion de Notifier."); MessageBus.Remove <RequestStop>(_notifier.Stop); MessageBus.Remove <ReplyStop>(NotifierStopOK); _areEsperaOperacion.Set(); }
//Solicitud de detener el componente internal void Stop(RequestStop req) { Builder.Output("Deteniendo DbHandler."); StopComponent(); Builder.Output("DbHandler detenido."); MessageBus.Send(new ReplyStop()); }
static private bool RegistrarMensajes() { try { // Enlaces adicionales MessageBus.Register <RequestClientConfig>(_dbHandler.SendClientConfig); MessageBus.Register <RequestSystemConfig>(_dbHandler.SendSystemConfig); MessageBus.Register <RequestQueueInfo>(_clientManager.DoRequestQueueInfo); MessageBus.Register <SendHeartbeat>(_clientManager.ReceiveHearbeat); MessageBus.Register <SupervisorClientLogEvent>(ClientLogonEvent); MessageBus.Register <RemoteConsoleText>(_remoteMonitor.SendRemoteConsoleText); MessageBus.Register <SupervisorClientRequestConsoleText>(SendRemoteTextCache); MessageBus.Register <RequestSaveConfig>(_dbHandler.Save); MessageBus.Register <RequestUpdateClient>(_clientManager.DoUpdateClient); MessageBus.Register <RequestCreateClient>(_clientManager.DoCreateClient); MessageBus.Register <RequestDeleteClient>(_clientManager.DoDeleteClient); MessageBus.Register <RequestPauseClient>(_clientManager.DoPauseClient); MessageBus.Register <RequestResumeClient>(_clientManager.DoResumeClient); MessageBus.Register <RequestUpdateSystem>(DoUpdateSystem); MessageBus.Register <RequestStartHbServer>(_clientManager.DoRestartHbReceiver); return(true); } catch (Exception ex) { Builder.Output(string.Format("{0}.RegistrarMensajes: ocurrio una excepcion: {1}", ClassName, ex.Message), System.Diagnostics.TraceEventType.Error); return(false); } }
internal bool OpenDatabase() { try { SystemPlusClientData tmpDB; if (DatabaseExists()) { Builder.Output(ClassName + ": Archivo de datos de configuracion existente. Se abre.", System.Diagnostics.TraceEventType.Verbose); tmpDB = DeSerializarDeDisco(DatabaseName); } else { Builder.Output(ClassName + ": No existe archivo de datos de configuracion. Se crea nuevo.", System.Diagnostics.TraceEventType.Verbose); tmpDB = new SystemPlusClientData(); SerializarADisco(tmpDB, DatabaseName); } _dbRoot = tmpDB; return(true); } catch (Exception ex) { // guardar msg de error _dbRoot = null; ErrorMsg = ex.Message; return(false); } }
internal void ReceiveSystemConfig(SendSystemConfig req) { int port; string name; // Garantiza inicio de las propiedades con valores por defecto // si la configuracion no está actualizada. if (req.Data.ZyanServerPort == 0) { port = Constants.ZyanServerPort; } else { port = req.Data.ZyanServerPort; } if (string.IsNullOrEmpty(req.Data.ZyanServerName)) { name = Constants.ZyanServerName; } else { name = req.Data.ZyanServerName; } _zsName = name; _zsPort = port; Builder.Output(ClassName + ": recibidos datos de configuracion de sistema.", TraceEventType.Information); }
static private void DoFormEnd(FormEndEdit req) { string msg = req.AcceptChanges ? "Edicion aceptada." : "Edicion cancelada."; Builder.Output(msg); _editForm.Close(); }
public void ReceiveSystemConfig(SendSystemConfig req) { _sMtpServer = req.Data.SMtpServer; _source = req.Data.Source; _destination = req.Data.Destination; _password = req.Data.Password; Builder.Output(ClassName + ": recibidos datos de configuracion de sistema.", TraceEventType.Information); }
internal void ReceiveSystemConfig(SendSystemConfig data) { // guardando datos de config system _udpServerPort = data.Data.UdpServerPort; _udpServerIP = data.Data.ServerIpAdr; _systemTimeout = data.Data.TimeoutStartRestart; _restCount = data.Data.RestartAttemps; Builder.Output(ClassName + ": recibidos datos de configuracion de sistema.", TraceEventType.Information); }
/// <summary> /// Realiza los subprocesos de chequeo de los clientes, en un hilo propio. /// </summary> private void QueueManagerThreadProcess() { try { while (_continueThread) { // Resetear para impedir edicion de clientes mientras se ejecuta el ciclo de procesos _areClientUpdate.Reset(); // Ciclo para intentar reiniciar clientes en lista de timeouts // Si se reinicia, se mueve a recover list, sino, se mueve a deadlist ClientTryToRestart(); // Ciclo para detectar clientes que no envian hearbeat despues de reiniciar la aplicacion // // !!!!! ******* !!!!!!!!! ********* !!!!!!!!! // Importante: // Este metodo debe invocarse siempre antes que CheckRecoverTimeout. De lo contrario // los clientes sin enviar en mucho tiempo HB se mueven a la lista de Detenidos y se reinician // y regresan a esta lista en circulo vicioso, sin ser detectados. CheckRecoverDead(); // Ciclo para detectar timeouts durante la operacion // mueve de _workList a _timeOutList si el intervalo es mayor que el timeout configurado en el cliente CheckOperationTimeout(); // Ciclo para detectar timeouts posteriores al reinicio de la aplicacion CheckRecoverTimeout(); // Ciclo para detectar timeouts al iniciar operacion // mueve de _startList a _timeOutList si el intervalo es mayor que el valor configurado // en el sistema como Timeout al Iniciar/Reiniciar. CheckInitialTimeout(); // Contador de ciclos, indica salva periodica de los datos HB de clientes if (_count++ > _loops) { _count = 0; MessageBus.Send(new RequestSaveConfig()); } // Seteando para permitir acceso a colas. _areClientUpdate.Set(); Thread.Sleep(450); } } catch (Exception ex) { Builder.Output(ClassName + ": QueueManagerThreadProcess Error: " + ex.Message, TraceEventType.Error); Log.WriteEntry(ClassName, "QueueManagerThreadProcess", TraceEventType.Error, ex.Message); throw; } }
private void SerializarADisco(SystemPlusClientData obj, string file) { if (obj != null) { Serializer.Serialize <SystemPlusClientData>(obj, file); } else { Builder.Output("Intentando serializar referencia nula.", System.Diagnostics.TraceEventType.Warning); } }
static private void ZyanServerStartOK(ReplyOK reply) { Builder.Output("Confirmado inicio de ZyanServer."); MessageBus.Remove <RequestStart>(_zyanServer.Start); MessageBus.Remove <RequestStop>(_zyanServer.Stop); MessageBus.Remove <ReplyOK>(ZyanServerStartOK); MessageBus.Remove <SendSystemConfig>(_zyanServer.ReceiveSystemConfig); Detenerse = false; _areEsperaOperacion.Set(); }
private void ClientLoggedOn(object sender, LoginEventArgs e) { string msg = "Usuario: {0} Ip: {1} inicia sesion de supervision en: {2}"; string name = string.IsNullOrEmpty(e.Identity.Name) ? "anonimo" : e.Identity.Name; Builder.Output(string.Format(msg, name, e.ClientAddress, e.Timestamp.ToString()), TraceEventType.Verbose); MessageBus.Send(new SupervisorClientLogEvent(e.ClientAddress, SupervisorLoginType.Logon, e.Identity.Name, e.Timestamp)); }
static private void DetenerComponentes() { try { // Comienza descarga Builder.Output("Terminando ejecucion del servicio."); // Salvar datos MessageBus.Send(new RequestSaveConfig()); // Terminar modulos consecutivamente esperando confirmacion. Builder.Output("Deteniendo componentes."); // ClientManager _areEsperaOperacion.Reset(); MessageBus.Register <RequestStop>(_clientManager.Stop); MessageBus.Register <ReplyStop>(ClientManagerStopOK); MessageBus.Send(new RequestStop()); _areEsperaOperacion.WaitOne(); // ZyanServer _areEsperaOperacion.Reset(); MessageBus.Register <RequestStop>(_zyanServer.Stop); MessageBus.Register <ReplyStop>(ZyanServerStopOK); MessageBus.Send(new RequestStop()); _areEsperaOperacion.WaitOne(); // Notificar fin de sistema antes de detener Notifier NotificarFinSistema(); // Notifier _areEsperaOperacion.Reset(); MessageBus.Register <RequestStop>(_notifier.Stop); MessageBus.Register <ReplyStop>(NotifierStopOK); MessageBus.Send(new RequestStop()); _areEsperaOperacion.WaitOne(); // Anular referencias _zyanServer = null; _notifier = null; _clientManager = null; Builder.Output("Componentes detenidos."); } catch (Exception ex) { Builder.Output(string.Format("{0}.DetenerComponentes: ocurrio una excepcion: {1}", ClassName, ex.Message), System.Diagnostics.TraceEventType.Error); } }
static private void EndWizard(FormEndEdit req) { if (req.AcceptChanges) { InstallService(); Builder.Output("Ejecutando InstallService."); } _editForm.Close(); _editForm = null; Builder.Output("Asistente de configuración terminado."); }
// Receptor ReplyStart // Continuar carga configuracion y ejecucion static private void DbHandlerStartOK(ReplyOK reply) { Builder.Output("DbHandler Start OK"); // Se elimina para que no ejecute al enviar este mensaje // para iniciar los otros modulos MessageBus.Remove <RequestStart>(_dbHandler.Start); MessageBus.Remove <RequestStop>(_dbHandler.Stop); MessageBus.Remove <ReplyOK>(DbHandlerStartOK); Detenerse = false; _areEsperaOperacion.Set(); }
static private void ExportData(string file) { Builder.Output("Exportando configuracion hacia archivo: " + file, TraceEventType.Verbose); if (_dbHandler.ExportConfig(file)) { Builder.Output("Configuracion exportada OK."); } else { Builder.Output("Error: " + _dbHandler.ErrorMsg); } }
public void In_RequestClientResume(RemReqResumeClient request) { Builder.Output(ClassName + ": recibe solicitud remota de terminar la pausa a un cliente.", TraceEventType.Verbose); try { MessageBus.Send(new RequestResumeClient(request.Id)); } catch (Exception ex) { //TODO no lanzar, registar en log, enviar error msg a cliente Out_SendError(new RemReplyConsoleText(new RemoteConsoleText(ex.Message, TraceEventType.Error))); } }
private void SendMail(EMessageAction action, EMessageStyle style, ClientData client, DateTime date) { PlainTextMessage mess = new PlainTextMessage(action, style, client.Name, date); HTMLMessage htmmess = new HTMLMessage(action, style, client.Name, date); MailMessage mailMessage = new MailMessage(); // Direciones mailMessage.From = new MailAddress(_source); mailMessage.To.Add(_destination); // Asunto mailMessage.Subject = mess.Subject; // Cuerpo en texto plano mailMessage.Body = mess.Body; // Add HTML View AlternateView altHtml = AlternateView.CreateAlternateViewFromString(htmmess.Body, null, "text/html"); mailMessage.AlternateViews.Add(altHtml); // Incorporar adjunto si esta configurado en el cliente // y es una accion Timeout o Dead bool UseAttach = client.LogAttachEnabled && (action == EMessageAction.Timeout) || (action == EMessageAction.Dead); FileStream fs = null; if (UseAttach && File.Exists(client.LogFilePath)) { fs = new FileStream(client.LogFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); mailMessage.Attachments.Add(new Attachment(fs, "Archivo Log", "text/plain")); } try { EnviaEmail(mailMessage); } catch (Exception ex) { Builder.Output(string.Format("{0}.SendMail: Ocurrió una excepción: {1}", ClassName, ex.Message), TraceEventType.Error); throw ex; } finally { if (fs != null) { fs.Close(); } } }
private void LoadClients() { if (_clientList.Count > 0) { // Creando listas de trabajo foreach (var item in _clientList.List) { ClientData client = item; ClientMoveToStartList(client); Builder.Output(string.Format("{0}: Cargado cliente: {1} Id: {2} Puerto: {3}", ClassName, client.Name, client.Id, client.Port), System.Diagnostics.TraceEventType.Verbose); } } }
public void In_RequestSystemUpdate(RemReqUpdateSystem request) { Builder.Output(ClassName + ": recibe solicitud remota de actualizar configuracion de sistema.", TraceEventType.Verbose); try { MessageBus.Send(new RequestUpdateSystem(request.Data)); } catch (Exception ex) { //TODO no lanzar, registar en log, enviar error msg a cliente //throw; Out_SendError(new RemReplyConsoleText(new RemoteConsoleText(ex.Message, TraceEventType.Error))); } }
private void RegisterComponent(int port, string name, RemoteMonitor instance) { TcpDuplexServerProtocolSetup protocol = new TcpDuplexServerProtocolSetup(port); _znHost = new ZyanComponentHost(name, protocol); //_znHost.EnableDiscovery(); //_znHost.RegisterComponent<IMonitor, RemoteMonitor>(ActivationType.Singleton); _znHost.RegisterComponent <IMonitor, RemoteMonitor>(instance); _znHost.ClientLoggedOn += ClientLoggedOn; _znHost.ClientLoggedOff += ClientLoggedOff; Builder.Output(string.Format(ClassName + ": registrado componente {0} en puerto {1}.", name, port), TraceEventType.Verbose); }