示例#1
0
        /// <summary>
        /// Разгрузка очередей перегруженных клиентов
        /// </summary>
        /// <param name="client">Потенциальный клиент на разгруженные книги</param>
        /// <param name="alignmentCoefficient">Коэффициент выравнивания загружености клиентов</param>
        /// <returns>Очередь разгруженых книг</returns>
        public Dictionary <string, Queue <string> > UnloadingQueuesClients(ClientSDB client, double alignmentCoefficient)
        {
            Dictionary <string, Queue <string> > unloadingBooksQueue = new Dictionary <string, Queue <string> >();
            DateTime reloadTimeRead = СalculationСriticalTimeRead(alignmentCoefficient);

            var selectedClient = from clientServer in ClientDictionary
                                 from lelaClientServer in clientServer.Value.GetClientServerDB().LevelLanguages
                                 from lelaClient in client.LevelLanguages
                                 where lelaClientServer.Language == lelaClient.Language &&
                                 clientServer.Value.GetClientServerDB().TimeRead > reloadTimeRead
                                 select clientServer.Value;

            foreach (var selectImitationActivity in selectedClient)
            {
                selectImitationActivity.SetWaitOneMutexJointOperation();
                ClientServerDB selectClientServer = selectImitationActivity.GetClientServerDB();
                unloadingBooksQueue.Add(selectClientServer.Address, new Queue <string>());
                while (selectClientServer.TimeRead > reloadTimeRead)
                {
                    if (selectClientServer.QueueBook.Count > 0)
                    {
                        string book = selectClientServer.QueueBook.Dequeue();
                        unloadingBooksQueue[selectClientServer.Address].Enqueue(book);
                        SetRecalculateTimeRead(selectClientServer.Address);
                    }
                }
            }
            return(unloadingBooksQueue);
        }
 /// <summary>
 /// Удаление клиента из систем сервера
 /// </summary>
 /// <param name="address">Электронный адресс клиента</param>
 private void DeleteClientServer(string address)
 {
     if (WorkClientGroup.ClientAvailability(address))
     {
         ClientServerDB clientServer = WorkClientGroup.CloneClient(address);
         WorkClientGroup.DeleteClient(address);
         WorkMongo.DeleteClient(address);
         try
         {
             WorkMySQL.DeleteClient(address);
             WorkRabbit.RedistributionQueue(clientServer.QueueBook, WorkRabbit.ExchangeBook, WorkRabbit.RoutingBook);
         }
         catch (MySqlException)
         {
             WorkMongo.AddClient(clientServer);
             StopServer();
         }
         catch (RabbitmqException)
         {
             WorkMongo.AddClient(clientServer);
             WorkMySQL.SetSubscriptionOn(address);
             StopServer();
         }
     }
 }
示例#3
0
        /// <summary>
        /// Добавление информации о клиенте
        /// </summary>
        /// <param name="clientServer">Объект клиента</param>
        public void AddClientInfo(ClientServerDB clientServer)
        {
            string sqlCommand = "INSERT INTO clients (Address, Surname, Name, PagesPerDay, ReadingIntervalActive, " +
                                "ReadingIntervalPassive, DataRegistration, Subscription) " +
                                "VALUES (@Addres, @Surname, @Name, @PagesPerDay, @ReadingIntervalActive, " +
                                "@ReadingIntervalPassive, @DataRegistration, @Subscription)";

            try
            {
                ConnectionMySQL.Open();
                MySqlCommand command = new MySqlCommand(sqlCommand, ConnectionMySQL);
                command.Parameters.AddWithValue("@Addres", clientServer.Address);
                command.Parameters.AddWithValue("@Surname", clientServer.Surname);
                command.Parameters.AddWithValue("@Name", clientServer.Name);
                command.Parameters.AddWithValue("@PagesPerDay", clientServer.PagesPerDay);
                command.Parameters.AddWithValue("@ReadingIntervalActive", clientServer.ReadingIntervalActive);
                command.Parameters.AddWithValue("@ReadingIntervalPassive", clientServer.ReadingIntervalPassive);
                command.Parameters.AddWithValue("@DataRegistration", clientServer.DataRegistration);
                command.Parameters.AddWithValue("@Subscription", "Подписан");
                command.ExecuteNonQuery();
            }
            catch (Exception exception)
            {
                Log.Error(exception.ToString);
                throw new MySqlException();
            }
            finally
            {
                ConnectionMySQL.Close();
            }
        }
        /// <summary>
        /// Добавление клиента в системы сервера
        /// </summary>
        /// <param name="client">Клиент</param>
        private void AddClientServer(ClientSDB client)
        {
            if (!WorkClientGroup.ClientAvailability(client.Address) && !WorkMySQL.ClientAvailability(client.Address))
            {
                ClientServerDB clientServer = new ClientServerDB(client);

                WorkClientGroup.AddClient(clientServer);
                WorkMongo.AddClient(clientServer);
                try
                {
                    WorkMySQL.AddClient(clientServer);
                    WorkRabbit.RedistributionQueue(WorkRabbit.QueueUnallocated, WorkRabbit.ExchangeBook, WorkRabbit.RoutingBook);
                }
                catch (MySqlException)
                {
                    WorkMongo.DeleteClient(clientServer.Address);
                    StopServer();
                }
                catch (RabbitmqException)
                {
                    WorkMongo.DeleteClient(clientServer.Address);
                    WorkMySQL.FullDeleteClient(clientServer.Address);
                    StopServer();
                }
            }
        }
示例#5
0
 /// <summary>
 /// Добавление языков клиента и уровня их владения
 /// </summary>
 /// <param name="clientServer">Объект клиента</param>
 public void AddLevelLanguages(ClientServerDB clientServer)
 {
     foreach (LevelLanguageSDB ll in clientServer.LevelLanguages)
     {
         AddLevelLanguage(clientServer, ll);
     }
 }
示例#6
0
        /// <summary>
        /// Возвращение поверхностной копии клиента
        /// </summary>
        /// <param name="address">Электронный адресс клиента</param>
        /// <returns>Поверхностной копия клиента</returns>
        public ClientServerDB CloneClient(string address)
        {
            ClientServerDB clientServer = null;

            if (ClientDictionary.ContainsKey(address))
            {
                clientServer = (ClientServerDB)ClientDictionary[address].GetClientServerDB().Clone();
            }
            return(clientServer);
        }
示例#7
0
 /// <summary>
 /// Конструктор объекта имитации деятельности клиента
 /// </summary>
 /// <param name="clientServer"></param>
 /// <param name="serverDB"></param>
 public ImitationClientActivity(ClientServerDB clientServer, ControlServerDB serverDB)
 {
     ServerDB            = serverDB;
     ClientServer        = clientServer;
     ImitationActivity   = new Thread(new ThreadStart(GettingAndReadingBook));
     MutexJointOperation = new Mutex();
     MySqlConnection     = new MySqlSDB(ServerDB);
     MongoConnection     = new MongoDbSDB(ServerDB);
     WaitHandler         = new AutoResetEvent(true);
 }
 /// <summary>
 /// Добавление клиента
 /// </summary>
 /// <param name="clientServer">Объект клиента</param>
 public void AddClient(ClientServerDB clientServer)
 {
     try
     {
         CollectionMongo.InsertOne(clientServer);
     }
     catch (Exception exception)
     {
         Log.Error(exception.ToString);
         ServerDB.StopServer();
     }
 }
        /// <summary>
        /// Создание рассширеного объекта клиента для записи в MongoDB (корректировка времени)
        /// </summary>
        /// <returns></returns>
        public ClientServerDB ConvertMongoDate()
        {
            ClientServerDB clientserverDBMongo = new ClientServerDB();

            clientserverDBMongo.Surname                = Surname;
            clientserverDBMongo.Name                   = Name;
            clientserverDBMongo.Address                = Address;
            clientserverDBMongo.PagesPerDay            = PagesPerDay;
            clientserverDBMongo.ReadingIntervalActive  = ReadingIntervalActive;
            clientserverDBMongo.ReadingIntervalPassive = ReadingIntervalPassive;
            clientserverDBMongo.LevelLanguages         = LevelLanguages;
            clientserverDBMongo.DataRegistration       = DataRegistration.AddHours(3);
            clientserverDBMongo.queueBook              = queueBook;
            clientserverDBMongo.TimeReadActive         = TimeReadActive.AddHours(3);
            clientserverDBMongo.TimeRead               = TimeRead.AddHours(3);
            return(clientserverDBMongo);
        }
示例#10
0
        /// <summary>
        /// Перерасчет даты-времени освобождения клиента от чтения
        /// </summary>
        /// <param name="clientServer">Клиент сервера</param>
        /// <returns>Даты-время освобождения клиента от чтения</returns>
        public DateTime RecalculateTimeRead(string address)
        {
            ClientServerDB clientServer          = ClientDictionary[address].GetClientServerDB();
            int            queueBookCount        = clientServer.QueueBook.Count;
            DateTime       nowTime               = DateTime.UtcNow.ToLocalTime();
            DateTime       timeReadRecalculation = clientServer.TimeReadActive < nowTime ? nowTime : clientServer.TimeReadActive;

            for (int i = 0; i < queueBookCount; i++)
            {
                string bookJSON = clientServer.QueueBook.Dequeue();
                clientServer.QueueBook.Enqueue(bookJSON);
                BookSDB book      = JsonSerializer.Deserialize <BookSDB>(bookJSON);
                double  timeSleep = ServerDB.TimeReadingBook(clientServer, book, timeReadRecalculation);
                timeReadRecalculation = timeReadRecalculation.AddSeconds(timeSleep);
            }
            return(timeReadRecalculation);
        }
        /// <summary>
        /// Расчет времени чтения книги
        /// </summary>
        /// <param name="clientServer">Клиент сервера</param>
        /// <param name="book">Книги</param>
        /// <param name="dataTime">Дата-время, относительно которого производится расчет</param>
        /// <returns>Время чтения книги (в секундах)</returns>
        public double TimeReadingBook(ClientServerDB clientServer, BookSDB book, DateTime dataTime)
        {
            double timeReadingBook;                                                                         //время чтения книги
            int    level = 0;                                                                               //уровень владения языком

            foreach (LevelLanguageSDB lela in clientServer.LevelLanguages)
            {
                if (lela.Language == book.Language)
                {
                    level = lela.Level;
                    break;
                }
            }
            if (level == 0)
            {
                throw new Exception($"Клиент не владеет языком {book.Language}");
            }
            TimeSpan interval = dataTime - clientServer.DataRegistration;                                                     //интервал времени от данного до времени регистрации
            int      readingIntervalActiveSecond  = clientServer.ReadingIntervalActive * DaysSecond;                          //время активного чтения в цикле
            int      readingIntervalPassiveSecond = clientServer.ReadingIntervalPassive * DaysSecond;                         //время пассивного чтения чтения в цикле
            int      cycleReading           = readingIntervalActiveSecond + readingIntervalPassiveSecond;                     //время цикла чтения
            double   levelPagesPerCycle     = clientServer.ReadingIntervalActive * clientServer.PagesPerDay * (level / 10.0); //количество читаемых страниц в цикл
            double   balanseInterval        = interval.TotalSeconds % (double)cycleReading;                                   //текущее время нового цикла
            double   remainingActiveCycle   = readingIntervalActiveSecond - balanseInterval;                                  //оставшееся время цикла активного чтения
            double   timeReadingBookNCCycle = (double)(book.Pages % levelPagesPerCycle) / (double)levelPagesPerCycle          //время чтения неполного цикла
                                              * (double)readingIntervalActiveSecond;
            int TimeReadingBookFullCycle = (int)(book.Pages / levelPagesPerCycle) * cycleReading;                             //время чтения полных циклов

            if (balanseInterval >= readingIntervalActiveSecond)
            {
                timeReadingBook = TimeReadingBookFullCycle + timeReadingBookNCCycle + (cycleReading - balanseInterval);
            }
            else
            {
                if (remainingActiveCycle > timeReadingBookNCCycle)
                {
                    timeReadingBook = TimeReadingBookFullCycle + timeReadingBookNCCycle;
                }
                else
                {
                    timeReadingBook = TimeReadingBookFullCycle + timeReadingBookNCCycle + readingIntervalPassiveSecond;
                }
            }
            return(timeReadingBook);
        }
示例#12
0
        /// <summary>
        /// Добавление языка и уровня владения
        /// </summary>
        /// <param name="clientServer">Объект клиента</param>
        /// <param name="ll">Объект языка и уровня владения</param>
        public void AddLevelLanguage(ClientServerDB clientServer, LevelLanguageSDB ll)
        {
            string sqlCommand = "INSERT INTO levellanguages (AddressClient, Language, Level) " +
                                "VALUES (@AddressClient, @Language, @Level)";

            try
            {
                ConnectionMySQL.Open();
                MySqlCommand command = new MySqlCommand(sqlCommand, ConnectionMySQL);
                command.Parameters.AddWithValue("@AddressClient", clientServer.Address);
                command.Parameters.AddWithValue("@Language", (int)ll.Language);
                command.Parameters.AddWithValue("@Level", ll.Level);
                command.ExecuteNonQuery();
            }
            catch (Exception exception)
            {
                Log.Error(exception.ToString);
                throw new MySqlException();
            }
            finally
            {
                ConnectionMySQL.Close();
            }
        }
示例#13
0
        /// <summary>
        /// Добавление клиента
        /// </summary>
        /// <param name="clientServer">Объект клиента</param>
        public void AddClient(ClientServerDB clientServer)
        {
            ImitationClientActivity clientActivity = new ImitationClientActivity(clientServer, ServerDB);

            ClientDictionary.Add(clientServer.Address, clientActivity);
        }
示例#14
0
 /// <summary>
 /// Добавление клиента
 /// </summary>
 /// <param name="clientServer">Объект клиента</param>
 public void AddClient(ClientServerDB clientServer)
 {
     AddClientInfo(clientServer);
     AddLevelLanguages(clientServer);
 }
示例#15
0
        /// <summary>
        /// Изменение даты-времени освобождения от чтения на перерасчитаное
        /// </summary>
        /// <param name="address"></param>
        public void SetRecalculateTimeRead(string address)
        {
            ClientServerDB clientServer = ClientDictionary[address].GetClientServerDB();

            clientServer.TimeRead = RecalculateTimeRead(address);
        }
        /// <summary>
        /// Добавление, удаление клиентов
        /// </summary>
        /// <param name="e">Объект сообщения</param>
        /// <param name="channel">Канал связи с RabbitMQ</param>
        /// <param name="conn">Соединение с RabbitMQ</param>
        /// <param name="collection">Коллекция MongoDB</param>
        /// <param name="connectionString">Строка подключения MySQL</param>
        private static void AddingDeletedClient(BasicDeliverEventArgs e, IModel channel, IConnection conn, IMongoCollection <ClientServerDB> collection, string connectionString)
        {
            mutexDAD.WaitOne();
            //получение и распределение операций (добавление или отписка клиента)
            var body     = e.Body;
            var bodytype = e.BasicProperties.Type;
            var message  = Encoding.UTF8.GetString(body);

            //если добавление клиента
            if (bodytype == "Adding")
            {
                //сериализация клиента
                ClientSDB clientSDB = JsonSerializer.Deserialize <ClientSDB>(message);

                //проверка клиента на наличие в базе
                if (!listClient.ContainsKey(clientSDB.Address))
                {
                    //проверка в MySQL был ли клиент раннее подписан
                    string sqlcommand = "SELECT Address FROM clients WHERE Address = @Address";
                    bool   HasRows;
                    using (MySqlConnection connMySQL = new MySqlConnection(connectionString))
                    {
                        connMySQL.Open();
                        MySqlCommand   commandchek       = new MySqlCommand(sqlcommand, connMySQL);
                        MySqlParameter AddressCheckParam = new MySqlParameter("@Address", clientSDB.Address);
                        commandchek.Parameters.Add(AddressCheckParam);
                        MySqlDataReader reader = commandchek.ExecuteReader();
                        HasRows = reader.HasRows;
                    }
                    if (!HasRows)
                    {
                        //создание рассширеного объекта клиента и добавление его в список
                        ClientServerDB clientServerDB = new ClientServerDB(clientSDB, conn, collection, connectionString);
                        listClient.Add(clientServerDB.Address, clientServerDB);
                        //добавление клиента в MongoDB
                        ClientServerDB clientServerDBMongo = clientServerDB.ConvertMongoDate();
                        collection.InsertOne(clientServerDBMongo);
                        //добавление клиента в MySQL
                        using (MySqlConnection connMySQL = new MySqlConnection(connectionString))
                        {
                            connMySQL.Open();
                            MySqlCommand command = new MySqlCommand();
                            command.Connection  = connMySQL;
                            command.CommandText = "INSERT INTO clients (Address, Surname, Name, PagesPerDay, ReadingIntervalActive, " +
                                                  "ReadingIntervalPassive, DataRegistration, Subscription) " +
                                                  "VALUES (@Addres, @Surname, @Name, @PagesPerDay, @ReadingIntervalActive, @ReadingIntervalPassive, @DataRegistration, @Subscription)";
                            MySqlParameter AddressParam = new MySqlParameter("@Addres", clientServerDB.Address);
                            command.Parameters.Add(AddressParam);
                            MySqlParameter SurnameParam = new MySqlParameter("@Surname", clientServerDB.Surname);
                            command.Parameters.Add(SurnameParam);
                            MySqlParameter NameParam = new MySqlParameter("@Name", clientServerDB.Name);
                            command.Parameters.Add(NameParam);
                            MySqlParameter PagesPerDayParam = new MySqlParameter("@PagesPerDay", clientServerDB.PagesPerDay);
                            command.Parameters.Add(PagesPerDayParam);
                            MySqlParameter ReadingIntervalActiveParam = new MySqlParameter("@ReadingIntervalActive", clientServerDB.ReadingIntervalActive);
                            command.Parameters.Add(ReadingIntervalActiveParam);
                            MySqlParameter ReadingIntervalPassiveParam = new MySqlParameter("@ReadingIntervalPassive", clientServerDB.ReadingIntervalPassive);
                            command.Parameters.Add(ReadingIntervalPassiveParam);
                            MySqlParameter DataRegistrationParam = new MySqlParameter("@DataRegistration", clientServerDB.DataRegistration);
                            command.Parameters.Add(DataRegistrationParam);
                            MySqlParameter SubscriptionParam = new MySqlParameter("@Subscription", "Подписан");
                            command.Parameters.Add(SubscriptionParam);
                            command.ExecuteNonQuery();
                            foreach (LevelLanguageSDB ll in clientServerDB.LevelLanguages)
                            {
                                MySqlCommand commandll = new MySqlCommand();
                                commandll.Connection  = connMySQL;
                                commandll.CommandText = "INSERT INTO levellanguages (AddressClient, Language, Level) VALUES (@AddressClient, @Language, @Level)";
                                MySqlParameter AddressClientParam = new MySqlParameter("@AddressClient", clientServerDB.Address);
                                commandll.Parameters.Add(AddressClientParam);
                                MySqlParameter LanguageParam = new MySqlParameter("@Language", (int)ll.Language);
                                commandll.Parameters.Add(LanguageParam);
                                MySqlParameter LevelParam = new MySqlParameter("@Level", ll.Level);
                                commandll.Parameters.Add(LevelParam);
                                commandll.ExecuteNonQuery();
                            }
                        }
                    }
                }
            }
            //если отписка клиента
            else if (bodytype == "Deleted")
            {
                //проверка клиента на наличие в базе
                if (listClient.ContainsKey(message))
                {
                    //отписка клиента и удаление его из списка
                    listClient[message].Unsubscribe();
                    listClient.Remove(message);
                    //удаление клиента из MongoDB
                    collection.DeleteOne(p => p.Address == message);
                    //изменение статуса клиента на "Отписан" в MySQL
                    using (MySqlConnection connMySQL = new MySqlConnection(connectionString))
                    {
                        connMySQL.Open();
                        MySqlCommand command = new MySqlCommand();
                        command.Connection  = connMySQL;
                        command.CommandText = "UPDATE clients SET Subscription = 'Отписан' WHERE Address = @Address";
                        MySqlParameter AddressParam = new MySqlParameter("@Address", message);
                        command.Parameters.Add(AddressParam);
                        command.ExecuteNonQuery();
                    }
                }
            }
            channel.BasicAck(e.DeliveryTag, false);
            mutexDAD.ReleaseMutex();
        }
        /// <summary>
        /// Распределение книг
        /// </summary>
        /// <param name="e">Объект сообщения</param>
        /// <param name="channel">Канал связи с rabbitmq</param>
        /// <param name="collection">Коллекция MongoDB</param>
        private static void DistributionBook(BasicDeliverEventArgs e, IModel channel, IMongoCollection <ClientServerDB> collection)
        {
            mutexDAD.WaitOne();
            //получение и дессериализация книги
            var     body    = e.Body;
            var     message = Encoding.UTF8.GetString(body);
            BookSDB book    = JsonSerializer.Deserialize <BookSDB>(message);

            ClientServerDB clientSDB    = null;
            DateTime       timeRead     = new DateTime();           //промежуточное время окончания чтения книги
            DateTime       timeReadMain = new DateTime();           //время оканчания чтения книги
            DateTime       timeReadNow  = new DateTime();           //время начала чтения книги
            bool           first        = true;

            foreach (var client in listClient)
            {
                foreach (LevelLanguageSDB lela in client.Value.LevelLanguages)
                {
                    //проверка клиента на знание языка
                    if (book.Language == lela.Language)
                    {
                        //определение времени начала чтения книги
                        if (client.Value.TimeRead > DateTime.Now)
                        {
                            timeReadNow = client.Value.TimeRead;
                        }
                        else
                        {
                            timeReadNow = DateTime.Now;
                        }

                        //промежуточное определение времени окончания чтения книги
                        timeRead = timeReadNow.AddSeconds(client.Value.TimeReadingBook(book.Language, book.Pages, timeReadNow));
                        if (first || timeRead < timeReadMain)
                        {
                            //если клиент прочитает книгу быстрее предыдущего клиента, он становится активным клиентом
                            if (first)
                            {
                                first = false;
                            }
                            clientSDB    = client.Value;
                            timeReadMain = timeRead;
                        }
                    }
                }
            }
            //если подходящих клиентов не найденоб отправка книги в очередь не распределенных книг
            if (clientSDB == null)
            {
                channel.BasicPublish("ServerDB", "UnallocatedBook", null, e.Body);
                Console.WriteLine("UnallocatedBook" + " " + message);
            }
            else
            {
                //изменение времени оканчания чтения клиента и добавление книги ему в очередь
                clientSDB.TimeRead = timeReadMain;
                clientSDB.queueBook.Enqueue(message);

                //изменение времени оканчания чтения клиента и добавление книги в MongoDB
                var filter = Builders <ClientServerDB> .Filter.Eq("Address", clientSDB.Address);

                var updateTimeRead = Builders <ClientServerDB> .Update.Set(x => x.TimeRead, clientSDB.TimeRead.AddHours(3));

                collection.UpdateOne(filter, updateTimeRead);
                var updateBook = Builders <ClientServerDB> .Update.AddToSet(x => x.queueBook, message);

                collection.UpdateOne(filter, updateBook);

                //если клиент в данный момент не читает и у него в очереди нет книг, запуск потока получения и чтения книг
                if (clientSDB.readingBook.ThreadState == ThreadState.Unstarted || clientSDB.readingBook.ThreadState == ThreadState.Stopped)
                {
                    if (clientSDB.readingBook.ThreadState == ThreadState.Stopped)
                    {
                        clientSDB.readingBook = new Thread(new ThreadStart(clientSDB.ReadingBook));
                    }
                    clientSDB.readingBook.Start();
                }

                Console.WriteLine(clientSDB.Address + " " + message + clientSDB.TimeRead);
            }
            channel.BasicAck(e.DeliveryTag, false);
            mutexDAD.ReleaseMutex();
        }