9449 lines
676 KiB
Plaintext
9449 lines
676 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
// Copyright (c) 2022, ООО 1С-Софт
|
||
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
|
||
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
|
||
// Текст лицензии доступен по ссылке:
|
||
// https://creativecommons.org/licenses/by/4.0/legalcode
|
||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
#Область СлужебныйПрограммныйИнтерфейс
|
||
|
||
// Проверить необходимость обновления неразделенных данных информационной базы
|
||
// при смене версии конфигурации.
|
||
//
|
||
Функция НеобходимоОбновлениеНеразделенныхДанныхИнформационнойБазы() Экспорт
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
|
||
ВерсияМетаданных = Метаданные.Версия;
|
||
Если ПустаяСтрока(ВерсияМетаданных) Тогда
|
||
ВерсияМетаданных = "0.0.0.0";
|
||
КонецЕсли;
|
||
|
||
ВерсияОбщихДанных = ВерсияИБ(Метаданные.Имя, Истина);
|
||
|
||
Если НеобходимоВыполнитьОбновление(ВерсияМетаданных, ВерсияОбщихДанных) Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
|
||
Если НЕ ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
Запустить = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ЗапуститьОбновлениеИнформационнойБазы");
|
||
УстановитьПривилегированныйРежим(Ложь);
|
||
|
||
Если Запустить <> Неопределено И ЕстьПраваНаОбновлениеИнформационнойБазы() Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Ложь;
|
||
|
||
КонецФункции
|
||
|
||
// Выполнить неинтерактивное обновление данных ИБ.
|
||
//
|
||
// Параметры:
|
||
//
|
||
// ПараметрыОбновления - Структура:
|
||
// * ИсключениеПриНевозможностиБлокировкиИБ - Булево - если Ложь, тогда при неудачной
|
||
// попытке установки монопольного режима исключение не вызывается,
|
||
// а возвращается строка "ОшибкаУстановкиМонопольногоРежима".
|
||
//
|
||
// * ПриЗапускеКлиентскогоПриложения - Булево - начальное значение Ложь. Если указать Истина,
|
||
// тогда параметры работы программы не будут обновляться, т.к. при клиентском
|
||
// запуске они обновляются в самом начале (до авторизации пользователи и обновления ИБ).
|
||
// Параметр требуется для оптимизации клиентского режима запуска, чтобы не выполнять
|
||
// обновление параметров работы программы дважды.
|
||
// При внешнем вызове, например, в сеансе внешнего соединения, параметры работы
|
||
// программы должны быть обновлены до продолжения обновления ИБ.
|
||
// * Перезапустить - Булево - возвращаемое значение. Требование перезапуска,
|
||
// в некоторых случаях ПриЗапускеКлиентскогоПриложения, например,
|
||
// при возврате к конфигурации базы данных подчиненного узла РИБ,
|
||
// см. общий модуль ОбменДаннымиСервер процедуру.
|
||
// ВыполнитьСинхронизациюПриОтсутствииОбновленияИнформационнойБазы.
|
||
// * УстановленнаяБлокировкаИБ - см. БлокировкаИБ
|
||
// * ВФоне - Булево - если обновление информационной базы выполняется
|
||
// в фоне, то следует передавать Истина, иначе Ложь.
|
||
// * ВыполнятьОтложенныеОбработчики - Булево - если Истина, отложенное обновление будет выполнено
|
||
// в основном цикле обновления. Только для клиент-серверного режима работы.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - признак выполнения обработчиков обновления:
|
||
// "Успешно", "НеТребуется", "ОшибкаУстановкиМонопольногоРежима".
|
||
//
|
||
Функция ВыполнитьОбновлениеИнформационнойБазы(ПараметрыОбновления) Экспорт
|
||
|
||
ДополнительныеПараметры = ДействияПередОбновлениемИнформационнойБазы(ПараметрыОбновления);
|
||
Если ЗначениеЗаполнено(ДополнительныеПараметры.Возврат) Тогда
|
||
Возврат ДополнительныеПараметры.Возврат;
|
||
КонецЕсли;
|
||
|
||
ПараметрЗапускаКлиента = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ПараметрЗапуска");
|
||
ОтладкаОтложенногоОбновления = СтрНайти(НРег(ПараметрЗапускаКлиента), НРег("ОтладкаОтложенногоОбновления")) > 0;
|
||
РежимВыполненияОтложенногоОбновления = РежимВыполненияОтложенногоОбновления(ПараметрыОбновления);
|
||
ВыполнитьОтложенноеОбновлениеСейчас = Не ОтладкаОтложенногоОбновления И РежимВыполненияОтложенногоОбновления = "Монопольно";
|
||
|
||
ДополнительныеПараметры.Вставить("ВыполнитьОтложенноеОбновлениеСейчас", ВыполнитьОтложенноеОбновлениеСейчас);
|
||
ДополнительныеПараметры.Вставить("РежимВыполненияОтложенногоОбновления", РежимВыполненияОтложенногоОбновления);
|
||
|
||
ВыполнитьДействияПриОбновленииИнформационнойБазы(ПараметрыОбновления, ДополнительныеПараметры);
|
||
ВыполнитьДействияПослеОбновленияИнформационнойБазы(ПараметрыОбновления, ДополнительныеПараметры);
|
||
|
||
Возврат "Успешно";
|
||
|
||
КонецФункции
|
||
|
||
// Получить версию конфигурации или родительской конфигурации (библиотеки),
|
||
// которая хранится в информационной базе.
|
||
//
|
||
// Параметры:
|
||
// ИдентификаторБиблиотеки - Строка - имя конфигурации или идентификатор библиотеки.
|
||
// ПолучитьВерсиюОбщихДанных - Булево - если указать Истина, то при работе в модели сервиса будет
|
||
// возвращена версия в общих данных.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - версия.
|
||
//
|
||
// Пример использования:
|
||
// ВерсияКонфигурацииИБ = ВерсияИБ(Метаданные.Имя);
|
||
//
|
||
Функция ВерсияИБ(Знач ИдентификаторБиблиотеки, Знач ПолучитьВерсиюОбщихДанных = Ложь) Экспорт
|
||
|
||
УстановитьОтключениеБезопасногоРежима(Истина);
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
СтандартнаяОбработка = Истина;
|
||
Результат = "";
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриОпределенииВерсииИБ(ИдентификаторБиблиотеки, ПолучитьВерсиюОбщихДанных,
|
||
СтандартнаяОбработка, Результат);
|
||
|
||
КонецЕсли;
|
||
|
||
Если СтандартнаяОбработка Тогда
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ВерсииПодсистем.Версия
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
|
||
|ГДЕ
|
||
| ВерсииПодсистем.ИмяПодсистемы = &ИмяПодсистемы";
|
||
|
||
Запрос.УстановитьПараметр("ИмяПодсистемы", ИдентификаторБиблиотеки);
|
||
ТаблицаЗначений = Запрос.Выполнить().Выгрузить();
|
||
Результат = "";
|
||
Если ТаблицаЗначений.Количество() > 0 Тогда
|
||
Результат = СокрЛП(ТаблицаЗначений[0].Версия);
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
Возврат ?(ПустаяСтрока(Результат), "0.0.0.0", Результат);
|
||
|
||
КонецФункции
|
||
|
||
// Записывает в информационную базу версию конфигурации или родительской конфигурации (библиотеки).
|
||
//
|
||
// Параметры:
|
||
// ИдентификаторБиблиотеки - Строка - имя конфигурации или родительской конфигурации (библиотеки),
|
||
// НомерВерсии - Строка - номер версии.
|
||
// ЭтоОсновнаяКонфигурация - Булево - признак, что ИдентификаторБиблиотеки соответствует имени конфигурации.
|
||
// ВыполненаРегистрация - Булево - признак, что выполнена регистрация данных для отложенного обновления.
|
||
//
|
||
Процедура УстановитьВерсиюИБ(Знач ИдентификаторБиблиотеки, Знач НомерВерсии, Знач ЭтоОсновнаяКонфигурация, ВыполненаРегистрация = Неопределено) Экспорт
|
||
|
||
СтандартнаяОбработка = Истина;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриУстановкеВерсииИБ(ИдентификаторБиблиотеки, НомерВерсии, СтандартнаяОбработка, ЭтоОсновнаяКонфигурация);
|
||
|
||
КонецЕсли;
|
||
|
||
Если Не СтандартнаяОбработка Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
НаборЗаписей = РегистрыСведений.ВерсииПодсистем.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИмяПодсистемы.Установить(ИдентификаторБиблиотеки);
|
||
|
||
НоваяЗапись = НаборЗаписей.Добавить();
|
||
НоваяЗапись.ИмяПодсистемы = ИдентификаторБиблиотеки;
|
||
НоваяЗапись.Версия = НомерВерсии;
|
||
НоваяЗапись.ЭтоОсновнаяКонфигурация = ЭтоОсновнаяКонфигурация;
|
||
Если ВыполненаРегистрация <> Неопределено Тогда
|
||
НоваяЗапись.ВыполненаРегистрацияОтложенныхОбработчиков = ВыполненаРегистрация;
|
||
КонецЕсли;
|
||
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
// Записывает информацию о результате регистрации отложенных обработчиков на плане обмена.
|
||
//
|
||
Процедура ОтметитьРегистрациюОтложенныхОбработчиковОбновления(ИмяПодсистемы = Неопределено, Значение = Истина) Экспорт
|
||
|
||
СтандартнаяОбработка = Истина;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриОтметкеРегистрацииОтложенныхОбработчиковОбновления(ИмяПодсистемы, Значение, СтандартнаяОбработка);
|
||
КонецЕсли;
|
||
|
||
Если Не СтандартнаяОбработка Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
НаборЗаписей = РегистрыСведений.ВерсииПодсистем.СоздатьНаборЗаписей();
|
||
Если ИмяПодсистемы <> Неопределено Тогда
|
||
НаборЗаписей.Отбор.ИмяПодсистемы.Установить(ИмяПодсистемы);
|
||
КонецЕсли;
|
||
НаборЗаписей.Прочитать();
|
||
|
||
Если НаборЗаписей.Количество() = 0 Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Для Каждого ЗаписьРегистра Из НаборЗаписей Цикл
|
||
ЗаписьРегистра.ВыполненаРегистрацияОтложенныхОбработчиков = Значение;
|
||
КонецЦикла;
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
// Возвращает режим обновления данных информационной базы.
|
||
// Допускается вызывать только до начала обновления информационной базы (иначе возвращает "ОбновлениеВерсии").
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - "НачальноеЗаполнение", если это первый запуск пустой базы (области данных);
|
||
// "ОбновлениеВерсии", если выполняется первый запуск после обновление конфигурации базы данных;
|
||
// "ПереходСДругойПрограммы", если выполняется первый запуск после обновление конфигурации базы данных,
|
||
// в которой изменилось имя основной конфигурации.
|
||
//
|
||
Функция РежимОбновленияДанных() Экспорт
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
СтандартнаяОбработка = Истина;
|
||
РежимОбновленияДанных = "";
|
||
|
||
ИмяОсновнойКонфигурации = Метаданные.Имя;
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
Для каждого ИмяПодсистемы Из ОписанияПодсистем.Порядок Цикл
|
||
ОписаниеПодсистемы = ОписанияПодсистем.ПоИменам.Получить(ИмяПодсистемы); // см. СтандартныеПодсистемыПовтИсп.НовоеОписаниеПодсистемы
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеПодсистемы.ОсновнойСерверныйМодуль) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ОписаниеПодсистемы.Имя <> ИмяОсновнойКонфигурации Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Модуль = ОбщегоНазначения.ОбщийМодуль(ОписаниеПодсистемы.ОсновнойСерверныйМодуль);
|
||
Модуль.ПриОпределенииРежимаОбновленияДанных(РежимОбновленияДанных, СтандартнаяОбработка);
|
||
КонецЦикла;
|
||
|
||
Если НЕ СтандартнаяОбработка Тогда
|
||
ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("ПриОпределенииРежимаОбновленияДанных", "РежимОбновленияДанных",
|
||
РежимОбновленияДанных, Тип("Строка"));
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Недопустимое значение параметра %1 в %2.
|
||
|Ожидалось: %3, %4 или %5; передано значение: %6 (тип %7).'"),
|
||
"РежимОбновленияДанных", "ПриОпределенииРежимаОбновленияДанных",
|
||
"НачальноеЗаполнение", "ОбновлениеВерсии", "ПереходСДругойПрограммы",
|
||
РежимОбновленияДанных, ТипЗнч(РежимОбновленияДанных));
|
||
ОбщегоНазначенияКлиентСервер.Проверить(РежимОбновленияДанных = "НачальноеЗаполнение"
|
||
Или РежимОбновленияДанных = "ОбновлениеВерсии" Или РежимОбновленияДанных = "ПереходСДругойПрограммы", Сообщение);
|
||
Возврат РежимОбновленияДанных;
|
||
КонецЕсли;
|
||
|
||
Результат = Неопределено;
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриОпределенииРежимаОбновленияОбластиДанных(СтандартнаяОбработка, Результат);
|
||
КонецЕсли;
|
||
|
||
Если НЕ СтандартнаяОбработка Тогда
|
||
Возврат Результат;
|
||
КонецЕсли;
|
||
|
||
Возврат РежимОбновленияДанныхВЛокальномРежимеРаботы();
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
Функция ПараметрыОтбораОбработчиков() Экспорт
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("ПолучатьРазделенные", Ложь);
|
||
Результат.Вставить("РежимОбновления", "Монопольно");
|
||
Результат.Вставить("УчитыватьПервыйОбменВРИБ", Ложь);
|
||
Результат.Вставить("ПервыйОбменВРИБ", Ложь);
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция ОбработчикиОбновленияВИнтервале(Знач ИсходнаяТаблицаОбработчиков, Знач ВерсияОт, Знач ВерсияДо,
|
||
Знач ПараметрыОтбораОбработчиков = Неопределено) Экспорт
|
||
|
||
ПараметрыОтбора = ПараметрыОтбораОбработчиков;
|
||
Если ПараметрыОтбора = Неопределено Тогда
|
||
ПараметрыОтбора = ПараметрыОтбораОбработчиков();
|
||
КонецЕсли;
|
||
// Добавление номера в таблицу, для упорядочивания в порядке добавления.
|
||
ВсеОбработчики = ИсходнаяТаблицаОбработчиков.Скопировать();
|
||
|
||
ВсеОбработчики.Колонки.Добавить("НомерПоПорядку", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0)));
|
||
Для Индекс = 0 По ВсеОбработчики.Количество() - 1 Цикл
|
||
СтрокаОбработчика = ВсеОбработчики[Индекс];
|
||
СтрокаОбработчика.НомерПоПорядку = Индекс + 1;
|
||
КонецЦикла;
|
||
|
||
ОтметитьОбработчикиНовыхПодсистем(ВсеОбработчики);
|
||
|
||
// Подготовка параметров
|
||
ВыбиратьРазделенныеОбработчики = Истина;
|
||
ВыбиратьНеразделенныеОбработчики = Истина;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Если ПараметрыОтбора.ПолучатьРазделенные Тогда
|
||
ВыбиратьНеразделенныеОбработчики = Ложь;
|
||
Иначе
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
ВыбиратьНеразделенныеОбработчики = Ложь;
|
||
Иначе
|
||
ВыбиратьРазделенныеОбработчики = Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
// Формирование дерева обработчиков.
|
||
Схема = ПолучитьОбщийМакет("ПолучениеДереваОбработчиковОбновления");
|
||
Схема.Параметры.Найти("ВыбиратьРазделенныеОбработчики").Значение = ВыбиратьРазделенныеОбработчики;
|
||
Схема.Параметры.Найти("ВыбиратьНеразделенныеОбработчики").Значение = ВыбиратьНеразделенныеОбработчики;
|
||
Схема.Параметры.Найти("ВерсияОт").Значение = ВерсияОт;
|
||
Схема.Параметры.Найти("ВерсияДо").Значение = ВерсияДо;
|
||
Схема.Параметры.Найти("ВесВерсииОт").Значение = ВесВерсии(Схема.Параметры.Найти("ВерсияОт").Значение);
|
||
Схема.Параметры.Найти("ВесВерсииДо").Значение = ВесВерсии(Схема.Параметры.Найти("ВерсияДо").Значение);
|
||
Схема.Параметры.Найти("ОперативноеОбновление").Значение = (ПараметрыОтбора.РежимОбновления = "Оперативно");
|
||
Схема.Параметры.Найти("ОтложенноеОбновление").Значение = (ПараметрыОтбора.РежимОбновления = "Отложенно");
|
||
Если ПараметрыОтбора.УчитыватьПервыйОбменВРИБ Тогда
|
||
Схема.Параметры.Найти("ПервыйОбменВРИБ").Значение = ПараметрыОтбора.ПервыйОбменВРИБ;
|
||
Схема.Параметры.Найти("ЭтоРИБСФильтром").Значение = СтандартныеПодсистемыПовтИсп.ИспользуетсяРИБ("СФильтром");
|
||
КонецЕсли;
|
||
|
||
Компоновщик = Новый КомпоновщикМакетаКомпоновкиДанных;
|
||
Макет = Компоновщик.Выполнить(Схема, Схема.НастройкиПоУмолчанию, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
|
||
|
||
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
|
||
ПроцессорКомпоновки.Инициализировать(Макет, Новый Структура("Обработчики", ВсеОбработчики), , Истина);
|
||
|
||
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
|
||
ПроцессорВывода.УстановитьОбъект(Новый ДеревоЗначений);
|
||
|
||
ВыполняемыеОбработчики = ПроцессорВывода.Вывести(ПроцессорКомпоновки);
|
||
|
||
КолонкаВерсия = ВыполняемыеОбработчики.Колонки.Версия; // КоллекцияКолонокТаблицыЗначений
|
||
КолонкаВерсия.Имя = "ВерсияРегистрации";
|
||
КолонкаГруппаВерсии = ВыполняемыеОбработчики.Колонки.ГруппаВерсии; // КоллекцияКолонокТаблицыЗначений
|
||
КолонкаГруппаВерсии.Имя = "Версия";
|
||
|
||
// Сортировка обработчиков по признаку "ОбщиеДанные".
|
||
Для Каждого Версия Из ВыполняемыеОбработчики.Строки Цикл
|
||
Версия.Строки.Сортировать("ОбщиеДанные Убыв", Истина);
|
||
КонецЦикла;
|
||
|
||
Возврат ВыполняемыеОбработчики;
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция НеобходимоВыполнитьОбновление(Знач ВерсияМетаданных, Знач ВерсияДанных) Экспорт
|
||
Возврат НЕ ПустаяСтрока(ВерсияМетаданных) И ВерсияДанных <> ВерсияМетаданных;
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция ВыполненаРегистрацияОтложенныхОбработчиковОбновления() Экспорт
|
||
|
||
УстановитьОтключениеБезопасногоРежима(Истина);
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат Истина; // В неразделенном режиме отложенное обновление не выполняется.
|
||
КонецЕсли;
|
||
|
||
СтандартнаяОбработка = Истина;
|
||
Результат = "";
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриПроверкеРегистрацииОтложенныхОбработчиковОбновления(Результат, СтандартнаяОбработка);
|
||
КонецЕсли;
|
||
|
||
Если Не СтандартнаяОбработка Тогда
|
||
Возврат Результат;
|
||
КонецЕсли;
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ВерсииПодсистем.ИмяПодсистемы
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
|
||
|ГДЕ
|
||
| ВерсииПодсистем.ВыполненаРегистрацияОтложенныхОбработчиков = ЛОЖЬ";
|
||
|
||
Результат = Запрос.Выполнить().Выгрузить();
|
||
Возврат Результат.Количество() = 0;
|
||
|
||
КонецФункции
|
||
|
||
// Возвращает Истина, если у пользователя не отключен показ описания изменений
|
||
// системы после обновления и есть непоказанные изменения.
|
||
//
|
||
Функция ПоказатьОписаниеИзмененийСистемы() Экспорт
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
Если СведенияОбОбновлении.ВыводитьОписаниеОбновлений = Ложь Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если Не ПравоДоступа("СохранениеДанныхПользователя", Метаданные) Тогда
|
||
// Анонимным пользователям новое в версии не показываем.
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если Не ПравоДоступа("Просмотр", Метаданные.ОбщиеФормы.ОписаниеИзмененийПрограммы) Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И Пользователи.ЭтоПолноправныйПользователь(, Истина) Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
ВывестиОписаниеИзмененийДляАдминистратора = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("ОбновлениеИБ", "ВывестиОписаниеИзмененийДляАдминистратора",,, ИмяПользователя());
|
||
Если ВывестиОписаниеИзмененийДляАдминистратора = Истина Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
|
||
ПоследняяВерсия = ПоследняяВерсияОтображенияИзмененийСистемы();
|
||
Если ПоследняяВерсия = Неопределено Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
|
||
Разделы = РазделыОписанияИзменений();
|
||
|
||
Если Разделы = Неопределено Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Возврат ПолучитьВерсииБольшеЗаданной(Разделы, ПоследняяВерсия).Количество() > 0;
|
||
|
||
КонецФункции
|
||
|
||
// Проверяет статус отложенных обработчиков обновления.
|
||
//
|
||
Функция СтатусНевыполненныхОбработчиков(ПриОбновлении = Ложь) Экспорт
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
|
||
Если ПриОбновлении Тогда
|
||
ВерсияДанных = ВерсияИБ(Метаданные.Имя);
|
||
ВерсияДанныхБезНомераСборки = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(ВерсияДанных);
|
||
ВерсияМетаданныхБезНомераСборки = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(Метаданные.Версия);
|
||
ПодредакцииРавны = (ВерсияДанныхБезНомераСборки = ВерсияМетаданныхБезНомераСборки);
|
||
|
||
Если ВерсияДанных = "0.0.0.0" Или ПодредакцииРавны Тогда
|
||
// В пределах четвертой цифры можно обновляться при наличии невыполненных
|
||
// отложенных обработчиков обновления.
|
||
Возврат "";
|
||
КонецЕсли;
|
||
|
||
ВерсияДереваОбработчиков = СведенияОбОбновлении.ВерсияДереваОбработчиков;
|
||
Если ВерсияДереваОбработчиков <> "" И ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияДереваОбработчиков, ВерсияДанных) > 0 Тогда
|
||
// Если в основном цикле обновления произошла ошибка, то при перезапуске не надо
|
||
// проверять дерево отложенных обработчиков, т.к. там будут еще невыполненные
|
||
// отложенные обработчики на текущую версию.
|
||
Возврат "";
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.Статус КАК Статус
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
|
|
||
|СГРУППИРОВАТЬ ПО
|
||
| ОбработчикиОбновления.Статус";
|
||
СтатусыОбработчиков = Запрос.Выполнить().Выгрузить();
|
||
|
||
Если СтатусыОбработчиков.Найти(Перечисления.СтатусыОбработчиковОбновления.НеВыполнялся) <> Неопределено Тогда
|
||
Возврат "СтатусНеВыполнено";
|
||
ИначеЕсли СтатусыОбработчиков.Найти(Перечисления.СтатусыОбработчиковОбновления.Ошибка) <> Неопределено Тогда
|
||
Возврат "СтатусОшибка";
|
||
ИначеЕсли СтатусыОбработчиков.Найти(Перечисления.СтатусыОбработчиковОбновления.Приостановлен) <> Неопределено Тогда
|
||
Возврат "СтатусПриостановлен";
|
||
Иначе
|
||
Возврат "";
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
// Выполняет все процедуры отложенного обновления в цикле за один вызов.
|
||
//
|
||
Процедура ВыполнитьОтложенноеОбновлениеСейчас(ПараметрыОбновления = Неопределено) Экспорт
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
|
||
Если СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления <> Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если СведенияОбОбновлении.ВремяНачалаОтложенногоОбновления = Неопределено Тогда
|
||
СведенияОбОбновлении.ВремяНачалаОтложенногоОбновления = ТекущаяДатаСеанса();
|
||
КонецЕсли;
|
||
|
||
Если ТипЗнч(СведенияОбОбновлении.НомерСеанса) <> Тип("СписокЗначений") Тогда
|
||
СведенияОбОбновлении.НомерСеанса = Новый СписокЗначений;
|
||
КонецЕсли;
|
||
СведенияОбОбновлении.НомерСеанса.Добавить(НомерСеансаИнформационнойБазы());
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
ОбработчикиВыполнялись = Истина;
|
||
Пока ОбработчикиВыполнялись Цикл
|
||
ОбработчикиВыполнялись = ВыполнитьОтложенныйОбработчикОбновления(ПараметрыОбновления);
|
||
Если ОбработчикиВыполнялись Тогда
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
Если СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно <> Неопределено Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Для внутреннего использования.
|
||
Функция ДобавитьПараметрыРаботыКлиентаПриЗапуске(Параметры) Экспорт
|
||
|
||
Параметры.Вставить("ВерсияДанныхОсновнойКонфигурации", ВерсияИБ(Метаданные.Имя));
|
||
Если НеобходимоОбновлениеНеразделенныхДанныхИнформационнойБазы() Тогда
|
||
Параметры.Вставить("НеобходимоОбновлениеНеразделенныхДанных");
|
||
КонецЕсли;
|
||
|
||
// Проверка продолжения работы.
|
||
ЭтоВызовПередНачаломРаботыСистемы = Параметры.ПолученныеПараметрыКлиента <> Неопределено;
|
||
ОписаниеОшибки = ИнформационнаяБазаЗаблокированаДляОбновления(, ЭтоВызовПередНачаломРаботыСистемы);
|
||
Если ЗначениеЗаполнено(ОписаниеОшибки) Тогда
|
||
Параметры.Вставить("ИнформационнаяБазаЗаблокированаДляОбновления", ОписаниеОшибки);
|
||
// Работа будет завершена.
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если ТребуетсяПроверитьЛегальностьПолученияОбновления() Тогда
|
||
Параметры.Вставить("ПроверитьЛегальностьПолученияОбновления");
|
||
КонецЕсли;
|
||
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
// АПК:581-выкл Используется при тестировании.
|
||
Функция ТребуетсяПроверитьЛегальностьПолученияОбновления() Экспорт
|
||
|
||
Если НЕ ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПроверкаЛегальностиПолученияОбновления") Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если СтандартныеПодсистемыСервер.ЭтоБазоваяВерсияКонфигурации() Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
ЛегальнаяВерсия = "";
|
||
|
||
Если РежимОбновленияДанныхВЛокальномРежимеРаботы() = "НачальноеЗаполнение" Тогда
|
||
ЛегальнаяВерсия = Метаданные.Версия;
|
||
Иначе
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
ЛегальнаяВерсия = СведенияОбОбновлении.ЛегальнаяВерсия;
|
||
КонецЕсли;
|
||
|
||
Возврат ЛегальнаяВерсия <> Метаданные.Версия;
|
||
|
||
КонецФункции
|
||
// АПК:581-вкл
|
||
|
||
// Возвращает текст причины блокировки, если требуется обновление ИБ и у текущего пользователя
|
||
// для этого недостаточно прав, иначе возвращает пустую строку.
|
||
//
|
||
// Параметры:
|
||
// УчитыватьПривилегированныйРежим - Булево - если указать Ложь, то при проверке прав текущего пользователя
|
||
// наличие привилегированного режима не будет учитываться.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - если база не заблокирована, тогда пустая строка, иначе сообщение о причине блокировки.
|
||
//
|
||
Функция ИнформационнаяБазаЗаблокированаДляОбновления(УчитыватьПривилегированныйРежим = Истина, ПриЗапуске = Неопределено) Экспорт
|
||
|
||
Сообщение = "";
|
||
|
||
ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
|
||
|
||
// Для входа в заблокированную базу достаточно только одного права администрирования.
|
||
Если УчитыватьПривилегированныйРежим Тогда
|
||
ЕстьПравоАдминистрирование = ПравоДоступа("Администрирование", Метаданные);
|
||
Иначе
|
||
ЕстьПравоАдминистрирование = ПравоДоступа("Администрирование", Метаданные, ТекущийПользовательИБ);
|
||
КонецЕсли;
|
||
|
||
СообщениеАдминистраторуСистемы =
|
||
НСтр("ru = 'Вход в программу временно невозможен в связи с обновлением на новую версию.
|
||
|Для завершения обновления версии программы требуются административные права
|
||
|(роли ""Администратор системы"" и ""Полные права"").'");
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
РазделениеВключено = ОбщегоНазначения.РазделениеВключено();
|
||
ДоступноИспользованиеРазделенныхДанных = ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
|
||
УстановитьПривилегированныйРежим(Ложь);
|
||
|
||
Если НеобходимоОбновлениеНеразделенныхДанныхИнформационнойБазы() Тогда
|
||
|
||
СообщениеАдминистраторуОбластиДанных =
|
||
НСтр("ru = 'Вход в приложение временно невозможен в связи с обновлением на новую версию.
|
||
|Обратитесь к администратору сервиса за подробностями.'");
|
||
|
||
Если ДоступноИспользованиеРазделенныхДанных Тогда
|
||
Сообщение = СообщениеАдминистраторуОбластиДанных;
|
||
|
||
ИначеЕсли НЕ ЕстьПраваНаОбновлениеИнформационнойБазы(УчитыватьПривилегированныйРежим, Ложь) Тогда
|
||
|
||
Если ЕстьПравоАдминистрирование Тогда
|
||
Сообщение = СообщениеАдминистраторуСистемы;
|
||
Иначе
|
||
Сообщение = СообщениеАдминистраторуОбластиДанных;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Сообщение;
|
||
КонецЕсли;
|
||
|
||
// Сообщение администратору сервиса не выдается.
|
||
Если РазделениеВключено И Не ДоступноИспользованиеРазделенныхДанных Тогда
|
||
Возврат "";
|
||
КонецЕсли;
|
||
|
||
Если ЕстьПраваНаОбновлениеИнформационнойБазы(УчитыватьПривилегированныйРежим, Истина) Тогда
|
||
Если ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы()
|
||
И ПриЗапуске = Истина Тогда
|
||
Результат = ОтметкаНачалаОбновления();
|
||
Если Не Результат.МожноВыполнятьОбновление Тогда
|
||
Сообщение = НСтр("ru = 'Вход в программу временно невозможен в связи с обновлением на новую версию.
|
||
|Обновление уже выполняется:
|
||
| компьютер - %1
|
||
| пользователь - %2
|
||
| сеанс - %3
|
||
| начат - %4
|
||
| приложение - %5'");
|
||
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
|
||
Результат.СеансОбновления.ИмяКомпьютера,
|
||
Результат.СеансОбновления.Пользователь,
|
||
Результат.СеансОбновления.НомерСеанса,
|
||
Результат.СеансОбновления.НачалоСеанса,
|
||
Результат.СеансОбновления.ИмяПриложения);
|
||
Возврат Сообщение;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
Возврат "";
|
||
КонецЕсли;
|
||
|
||
ТребуетсяПовторитьЗагрузкуСообщенияОбменаДаннымиПередЗапуском = Ложь;
|
||
Если ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()
|
||
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
МодульОбменДаннымиСлужебный = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСлужебный");
|
||
ТребуетсяПовторитьЗагрузкуСообщенияОбменаДаннымиПередЗапуском =
|
||
МодульОбменДаннымиСлужебный.ПовторитьЗагрузкуСообщенияОбменаДаннымиПередЗапуском();
|
||
КонецЕсли;
|
||
|
||
// В этих случаях запуск не блокируется.
|
||
Если Не ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы()
|
||
И Не ТребуетсяПроверитьЛегальностьПолученияОбновления()
|
||
И Не ТребуетсяПовторитьЗагрузкуСообщенияОбменаДаннымиПередЗапуском Тогда
|
||
Возврат "";
|
||
КонецЕсли;
|
||
|
||
// Во всех остальных случаях запуск блокируется.
|
||
Если ЕстьПравоАдминистрирование Тогда
|
||
Возврат СообщениеАдминистраторуСистемы;
|
||
КонецЕсли;
|
||
|
||
Если РазделениеВключено Тогда
|
||
// Сообщение пользователю сервиса.
|
||
Сообщение =
|
||
НСтр("ru = 'Вход в приложение временно невозможен в связи с обновлением на новую версию.
|
||
|Обратитесь к администратору сервиса за подробностями.'");
|
||
Иначе
|
||
// Сообщение пользователю локального режима.
|
||
Сообщение =
|
||
НСтр("ru = 'Вход в программу временно невозможен в связи с обновлением на новую версию.
|
||
|Обратитесь к администратору за подробностями.'");
|
||
КонецЕсли;
|
||
|
||
Возврат Сообщение;
|
||
|
||
КонецФункции
|
||
|
||
// Устанавливает состояние запуска обновления информационной.
|
||
// Требуется привилегированный режим.
|
||
//
|
||
// Параметры:
|
||
// Запуск - Булево - если установить Истина, состояние будет установлено,
|
||
// если установить Ложь, состояние будет снято.
|
||
//
|
||
Процедура УстановитьЗапускОбновленияИнформационнойБазы(Запуск) Экспорт
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
ТекущиеПараметры = Новый Соответствие(ПараметрыСеанса.ПараметрыКлиентаНаСервере);
|
||
|
||
Если Запуск = Истина Тогда
|
||
ТекущиеПараметры.Вставить("ЗапуститьОбновлениеИнформационнойБазы", Истина);
|
||
|
||
ИначеЕсли ТекущиеПараметры.Получить("ЗапуститьОбновлениеИнформационнойБазы") <> Неопределено Тогда
|
||
ТекущиеПараметры.Удалить("ЗапуститьОбновлениеИнформационнойБазы");
|
||
КонецЕсли;
|
||
|
||
ПараметрыСеанса.ПараметрыКлиентаНаСервере = Новый ФиксированноеСоответствие(ТекущиеПараметры);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Получает сведения об обновлении информационной базы
|
||
// из константы "СведенияОбОбновленииИБ".
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ВремяНачалаОбновления - Строка
|
||
// * ВремяОкончанияОбновления - Строка
|
||
// * ПродолжительностьОбновления - Строка
|
||
// * ВремяНачалаОтложенногоОбновления - Строка
|
||
// * ВремяОкончаниеОтложенногоОбновления - Строка
|
||
// * НомерСеанса - СписокЗначений
|
||
// * ПараметрыОбработчикаОбновления - Структура
|
||
// * ОтложенноеОбновлениеЗавершеноУспешно - Строка
|
||
// * ДеревоОбработчиков - ДеревоЗначений
|
||
// * ВерсияДереваОбработчиков - Строка
|
||
// * ВыводитьОписаниеОбновлений - Булево
|
||
// * ЛегальнаяВерсия - Строка
|
||
// * НовыеПодсистемы - Массив
|
||
// * УправлениеОтложеннымОбновлением - Структура
|
||
// * ОбрабатываемыеДанные - Соответствие
|
||
// * ТекущаяИтерацияОбновления - Число
|
||
// * ПланОтложенногоОбновления - Массив
|
||
// * СеансОбновления - Структура
|
||
// * ОписаниеПотоков - см. НовоеОписаниеПотоковРегистрацииДанныхОтложенногоОбновления
|
||
// * ВерсияУдалениеПатчей - Строка
|
||
//
|
||
Функция СведенияОбОбновленииИнформационнойБазы() Экспорт
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
Возврат НовыеСведенияОбОбновлении();
|
||
КонецЕсли;
|
||
|
||
СведенияОбОбновленииИБ = Константы.СведенияОбОбновленииИБ.Получить().Получить();
|
||
Если ТипЗнч(СведенияОбОбновленииИБ) <> Тип("Структура") Тогда
|
||
Возврат НовыеСведенияОбОбновлении();
|
||
КонецЕсли;
|
||
Если СведенияОбОбновленииИБ.Количество() = 1 Тогда
|
||
Возврат НовыеСведенияОбОбновлении();
|
||
КонецЕсли;
|
||
|
||
СведенияОбОбновленииИБ = НовыеСведенияОбОбновлении(СведенияОбОбновленииИБ);
|
||
Возврат СведенияОбОбновленииИБ;
|
||
|
||
КонецФункции
|
||
|
||
// Записывает данные по обновлению в константу "СведенияОбОбновленииИБ".
|
||
//
|
||
Процедура ЗаписатьСведенияОбОбновленииИнформационнойБазы(Знач СведенияОбОбновлении) Экспорт
|
||
|
||
Если СведенияОбОбновлении = Неопределено Тогда
|
||
НовоеЗначение = НовыеСведенияОбОбновлении();
|
||
Иначе
|
||
НовоеЗначение = СведенияОбОбновлении;
|
||
КонецЕсли;
|
||
|
||
МенеджерКонстанты = Константы.СведенияОбОбновленииИБ.СоздатьМенеджерЗначения();
|
||
МенеджерКонстанты.Значение = Новый ХранилищеЗначения(НовоеЗначение);
|
||
ОбновлениеИнформационнойБазы.ЗаписатьДанные(МенеджерКонстанты);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Записывает в константу продолжительность основного цикла обновления.
|
||
//
|
||
Процедура ЗаписатьВремяВыполненияОбновления(ВремяНачалаОбновления, ВремяОкончанияОбновления) Экспорт
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено() И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
СведенияОбОбновлении.ВремяНачалаОбновления = ВремяНачалаОбновления;
|
||
СведенияОбОбновлении.ВремяОкончанияОбновления = ВремяОкончанияОбновления;
|
||
|
||
ВремяВСекундах = ВремяОкончанияОбновления - ВремяНачалаОбновления;
|
||
|
||
Часы = Цел(ВремяВСекундах/3600);
|
||
Минуты = Цел((ВремяВСекундах - Часы * 3600) / 60);
|
||
Секунды = ВремяВСекундах - Часы * 3600 - Минуты * 60;
|
||
|
||
ПродолжительностьЧасы = ?(Часы = 0, "", СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 час'"), Часы));
|
||
ПродолжительностьМинуты = ?(Минуты = 0, "", СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 мин'"), Минуты));
|
||
ПродолжительностьСекунды = ?(Секунды = 0, "", СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 сек'"), Секунды));
|
||
ПродолжительностьОбновления = ПродолжительностьЧасы + " " + ПродолжительностьМинуты + " " + ПродолжительностьСекунды;
|
||
СведенияОбОбновлении.ПродолжительностьОбновления = СокрЛП(ПродолжительностьОбновления);
|
||
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Только для внутреннего использования.
|
||
Процедура ЗаписатьПодтверждениеЛегальностиПолученияОбновлений() Экспорт
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных()
|
||
Или СтандартныеПодсистемыСервер.ЭтоБазоваяВерсияКонфигурации() Тогда
|
||
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
СведенияОбОбновлении.ЛегальнаяВерсия = Метаданные.Версия;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Устанавливает флаг отображения описаний изменений версий по
|
||
// текущую версию включительно, если для пользователя флаг не
|
||
// был установлен ранее.
|
||
//
|
||
// Параметры:
|
||
// ИмяПользователя - Строка - имя пользователя, для которого
|
||
// необходимо установить флаг.
|
||
//
|
||
Процедура УстановитьФлагОтображенияОписанийДляНовогоПользователя(Знач ИмяПользователя) Экспорт
|
||
|
||
Если ПоследняяВерсияОтображенияИзмененийСистемы(ИмяПользователя) = Неопределено Тогда
|
||
УстановитьФлагОтображенияОписанийПоТекущуюВерсию(ИмяПользователя);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Повторно регистрирует обновляемые данные на плане обмена
|
||
// ОбновлениеИнформационнойБазы, требуется при загрузке данных
|
||
// из сервиса в коробку и обратно.
|
||
//
|
||
Процедура ПеререгистрироватьДанныеДляОтложенногоОбновления() Экспорт
|
||
|
||
ПараметрыИнициализированы = Ложь;
|
||
|
||
Обработчики = ОбработчикиДляОтложеннойРегистрацииДанных();
|
||
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
|
||
Если Не ПараметрыИнициализированы Тогда
|
||
ПараметрыОбработчикаСтруктура = ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке();
|
||
ПараметрыОбработчикаСтруктура.ПовторнаяРегистрация = Истина;
|
||
ПараметрыИнициализированы = Истина;
|
||
КонецЕсли;
|
||
|
||
ПараметрыОбработчикаСтруктура.Очередь = Обработчик.ОчередьОтложеннойОбработки;
|
||
ПараметрыОбработчикаСтруктура.ИмяОбработчика = Обработчик.ИмяОбработчика;
|
||
ПараметрыОбработчикаСтруктура.Вставить("ДанныеОбработчика", Новый Соответствие);
|
||
|
||
Если Обработчик.Многопоточный Тогда
|
||
ПараметрыОбработчикаСтруктура.ПараметрыВыборки =
|
||
ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки();
|
||
Иначе
|
||
ПараметрыОбработчикаСтруктура.ПараметрыВыборки = Неопределено;
|
||
КонецЕсли;
|
||
|
||
ПараметрыОбработчика = Новый Массив;
|
||
ПараметрыОбработчика.Добавить(ПараметрыОбработчикаСтруктура);
|
||
Попытка
|
||
Сообщение = НСтр("ru = 'Выполняется процедура заполнения данных
|
||
|""%1""
|
||
|отложенного обработчика обновления
|
||
|""%2"".'");
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
|
||
Обработчик.ПроцедураЗаполненияДанныхОбновления,
|
||
Обработчик.ИмяОбработчика);
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(Обработчик.ПроцедураЗаполненияДанныхОбновления, ПараметрыОбработчика);
|
||
Если Обработчик.Многопоточный Тогда
|
||
ИсправитьПолныеИменаВПараметрахВыборки(ПараметрыОбработчикаСтруктура.ПараметрыВыборки);
|
||
КонецЕсли;
|
||
Исключение
|
||
ЗаписатьОшибку(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'При вызове процедуры заполнения данных
|
||
|""%1""
|
||
|отложенного обработчика обновления
|
||
|""%2""
|
||
|произошла ошибка:
|
||
|""%3"".'"),
|
||
Обработчик.ПроцедураЗаполненияДанныхОбновления,
|
||
Обработчик.ИмяОбработчика,
|
||
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
|
||
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
ОписаниеОбрабатываемыхДанных = НовоеОписаниеОбрабатываемыхДанных(Обработчик.Многопоточный);
|
||
ОписаниеОбрабатываемыхДанных.ДанныеОбработчика = ПараметрыОбработчикаСтруктура.ДанныеОбработчика;
|
||
ОписаниеОбрабатываемыхДанных.ИмяОбработчика = Обработчик.ИмяОбработчика;
|
||
|
||
Если Обработчик.Многопоточный Тогда
|
||
ОписаниеОбрабатываемыхДанных.ПараметрыВыборки = ПараметрыОбработчикаСтруктура.ПараметрыВыборки;
|
||
КонецЕсли;
|
||
|
||
ОписаниеОбрабатываемыхДанных = Новый ХранилищеЗначения(ОписаниеОбрабатываемыхДанных, Новый СжатиеДанных(9));
|
||
УстановитьСвойствоОбработчика(Обработчик.ИмяОбработчика, "ОбрабатываемыеДанные", ОписаниеОбрабатываемыхДанных);
|
||
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Возвращает параметры отложенного обработчика обновления.
|
||
// Проверяет, есть ли сохраненные параметры у обработчика обновления
|
||
// и возвращает их.
|
||
//
|
||
// Параметры:
|
||
// Идентификатор - Строка
|
||
// - УникальныйИдентификатор - имя процедуры обработчика или
|
||
// его уникальный идентификатор.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - сохраненные параметры обработчика обновления.
|
||
//
|
||
Функция ПараметрыОтложенногоОбработчикаОбновления(Идентификатор) Экспорт
|
||
ОбработчикОбновления = ОбработчикОбновления(Идентификатор);
|
||
|
||
Если ОбработчикОбновления = Неопределено Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
Параметры = СтатистикаВыполнения["ПараметрыОбработчика"];
|
||
Если Параметры = Неопределено Тогда
|
||
Параметры = Новый Структура;
|
||
КонецЕсли;
|
||
|
||
Возврат Параметры;
|
||
КонецФункции
|
||
|
||
// Записывает параметры отложенного обработчика обновления
|
||
//
|
||
// Параметры:
|
||
// Идентификатор - Строка
|
||
// - УникальныйИдентификатор - имя процедуры обработчика или
|
||
// его уникальный идентификатор.
|
||
// Параметры - Структура - параметры, которые необходимо сохранить.
|
||
//
|
||
Процедура ЗаписатьПараметрыОтложенногоОбработчикаОбновления(Идентификатор, Параметры) Экспорт
|
||
ОбработчикОбновления = ОбработчикОбновления(Идентификатор);
|
||
|
||
Если ОбработчикОбновления = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
СтатистикаВыполнения.Вставить("ПараметрыОбработчика", Параметры);
|
||
|
||
УстановитьСвойствоОбработчика(Идентификатор,
|
||
"СтатистикаВыполнения",
|
||
Новый ХранилищеЗначения(СтатистикаВыполнения));
|
||
КонецПроцедуры
|
||
|
||
// Возвращает количество потоков обновления информационной базы.
|
||
//
|
||
// Если количество указано в параметре запуска "ЧислоПотоковОбновления", то возвращается оно.
|
||
// Иначе, если значение константы КоличествоПотоковОбновленияИнформационнойБазы установлено, то возвращается оно.
|
||
// Иначе возвращается значение по умолчанию, см. КоличествоПотоковОбновленияИнформационнойБазыПоУмолчанию.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - количество потоков.
|
||
//
|
||
Функция КоличествоПотоковОбновленияИнформационнойБазы() Экспорт
|
||
|
||
Если РазрешеноМногопоточноеОбновление() Тогда
|
||
Количество = 0;
|
||
ИмяПараметра = "ЧислоПотоковОбновления=";
|
||
Параметры = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ПараметрЗапуска");
|
||
ПозицияПараметра = СтрНайти(Параметры, ИмяПараметра);
|
||
|
||
Если ПозицияПараметра > 0 Тогда
|
||
ПозицияРазделителя = СтрНайти(Параметры, ";",, ПозицияПараметра + СтрДлина(ИмяПараметра));
|
||
Длина = ?(ПозицияРазделителя > 0, ПозицияРазделителя, СтрДлина(Параметры) + 1) - ПозицияПараметра;
|
||
ПотокиОбновления = СтрРазделить(Сред(Параметры, ПозицияПараметра, Длина), "=");
|
||
|
||
Попытка
|
||
Количество = Число(ПотокиОбновления[1]);
|
||
Исключение
|
||
ТекстИсключения = НСтр(
|
||
"ru = 'Укажите параметр запуска программы ""%1"" в формате
|
||
|""%1=Х"", где ""Х"" - максимальное количество потоков обновления.'");
|
||
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, "ЧислоПотоковОбновления");
|
||
ВызватьИсключение ТекстИсключения;
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
|
||
Если Количество = 0 Тогда
|
||
Количество = Константы.КоличествоПотоковОбновленияИнформационнойБазы.Получить();
|
||
|
||
Если Количество = 0 Тогда
|
||
Количество = КоличествоПотоковОбновленияИнформационнойБазыПоУмолчанию();
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Количество;
|
||
Иначе
|
||
Возврат 1;
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
// Возвращает итерации обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Массив из см. ИтерацияОбновления
|
||
//
|
||
Функция ИтерацииОбновления() Экспорт
|
||
|
||
ИмяОсновнойКонфигурации = Метаданные.Имя;
|
||
ИтерацияОбновлениеОсновнойПодсистемы = Неопределено;
|
||
|
||
ИтерацииОбновления = Новый Массив;
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
Для каждого ИмяПодсистемы Из ОписанияПодсистем.Порядок Цикл
|
||
ОписаниеПодсистемы = ОписанияПодсистем.ПоИменам.Получить(ИмяПодсистемы);
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеПодсистемы.ОсновнойСерверныйМодуль) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Модуль = ОбщегоНазначения.ОбщийМодуль(ОписаниеПодсистемы.ОсновнойСерверныйМодуль);
|
||
|
||
ИтерацияОбновления = ИтерацияОбновления(ОписаниеПодсистемы.Имя, ОписаниеПодсистемы.Версия,
|
||
ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления(), ОписаниеПодсистемы.Имя = ИмяОсновнойКонфигурации);
|
||
ИтерацияОбновления.ИмяОсновногоСерверногоМодуля = ОписаниеПодсистемы.ОсновнойСерверныйМодуль;
|
||
ИтерацияОбновления.ОсновнойСерверныйМодуль = Модуль;
|
||
ИтерацияОбновления.ПредыдущаяВерсия = ВерсияИБ(ОписаниеПодсистемы.Имя);
|
||
ИтерацииОбновления.Добавить(ИтерацияОбновления);
|
||
|
||
Модуль.ПриДобавленииОбработчиковОбновления(ИтерацияОбновления.Обработчики);
|
||
|
||
Если ОписаниеПодсистемы.Имя = ИмяОсновнойКонфигурации Тогда
|
||
ИтерацияОбновлениеОсновнойПодсистемы = ИтерацияОбновления;
|
||
КонецЕсли;
|
||
|
||
ПроверитьСвойстваОбработчиков(ИтерацияОбновления);
|
||
КонецЦикла;
|
||
|
||
Если ИтерацияОбновлениеОсновнойПодсистемы = Неопределено И ИмяОсновнойКонфигурации = "БиблиотекаСтандартныхПодсистем" Тогда
|
||
ТекстСообщения = НСтр("ru = 'Файл поставки 1С:Библиотека стандартных подсистем не предназначен для создания
|
||
|информационных баз по шаблону. Перед использованием необходимо
|
||
|ознакомиться с документацией на ИТС (http://its.1c.ru/db/bspdoc)'");
|
||
ВызватьИсключение ТекстСообщения;
|
||
КонецЕсли;
|
||
|
||
Возврат ИтерацииОбновления;
|
||
|
||
КонецФункции
|
||
|
||
// АПК:581-выкл Для механизма обновления ИБ в копии.
|
||
|
||
// Обновляет список выполняемых обработчиков обновления в регистрах сведений
|
||
// ОбработчикиОбновления и ОбработчикиОбновленияОбщихДанных.
|
||
//
|
||
Процедура ОбновитьСписокВыполняемыхОбработчиковОбновления(ИтерацииОбновления, ПервыйОбменВРИБ = Ложь, ТипыОбработчиков = Неопределено) Экспорт
|
||
|
||
ТолькоОтложенные = (ТипыОбработчиков = "Отложенные");
|
||
ТолькоМонопольные = (ТипыОбработчиков = "Монопольные");
|
||
|
||
Если Не ТолькоМонопольные Тогда
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
НезавершенныеОтложенныеОбработчики = НезавершенныеОтложенныеОбработчики(СведенияОбОбновлении);
|
||
КонецЕсли;
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
|
||
Если Не ТолькоМонопольные Тогда
|
||
ВерсииПодсистемНаНачалоОбновления = Новый Соответствие;
|
||
ОтложенноеОбновлениеЗавершеноУспешно = Неопределено;
|
||
ЗаполнитьВерсииПодсистем = Ложь;
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
ОтложенноеОбновлениеЗавершеноУспешно = Константы.ОтложенноеОбновлениеЗавершеноУспешно.Получить();
|
||
ВерсииПодсистемНаНачалоОбновления = СведенияОбОбновлении.ВерсииПодсистемНаНачалоОбновления;
|
||
ЗаполнитьВерсииПодсистем = Истина;
|
||
КонецЕсли;
|
||
|
||
Если ОтложенноеОбновлениеЗавершеноУспешно = Истина Тогда
|
||
ВерсииПодсистемНаНачалоОбновления.Очистить();
|
||
КонецЕсли;
|
||
|
||
СброситьСведенияОбОбновлении(СведенияОбОбновлении);
|
||
|
||
ПроверитьУникальностьИдентификаторовОтложенныхОбработчиков(ИтерацииОбновления);
|
||
КонецЕсли;
|
||
|
||
// АПК:1327-выкл нет конкурентной работы с регистром
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборРазделенныхОбработчиков = РегистрыСведений.ОбработчикиОбновления.СоздатьНаборЗаписей();
|
||
Если ТолькоМонопольные Тогда
|
||
// Остаются только отложенные обработчики, монопольные и оперативные добавляются заново.
|
||
НаборРазделенныхОбработчиков.Прочитать();
|
||
ТаблицаОбработчиков = НаборРазделенныхОбработчиков.Выгрузить();
|
||
|
||
ПараметрыОтбора = Новый Структура;
|
||
ПараметрыОтбора.Вставить("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
ТаблицаОбработчиков = ТаблицаОбработчиков.Скопировать(ПараметрыОтбора);
|
||
|
||
НаборРазделенныхОбработчиков.Загрузить(ТаблицаОбработчиков);
|
||
ИначеЕсли ТолькоОтложенные Тогда
|
||
// Монопольные и оперативные обработчики остаются, т.к. повторно регистрируются только отложенные.
|
||
НаборРазделенныхОбработчиков.Прочитать();
|
||
ТаблицаОбработчиков = НаборРазделенныхОбработчиков.Выгрузить();
|
||
|
||
ПараметрыОтбора = Новый Структура;
|
||
ПараметрыОтбора.Вставить("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Монопольно);
|
||
МонопольныеОбработчики = ТаблицаОбработчиков.Скопировать(ПараметрыОтбора);
|
||
|
||
ПараметрыОтбора.Вставить("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Оперативно);
|
||
ОперативныеОбработчики = ТаблицаОбработчиков.Скопировать(ПараметрыОтбора);
|
||
|
||
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(МонопольныеОбработчики, ОперативныеОбработчики);
|
||
|
||
НаборРазделенныхОбработчиков.Загрузить(ОперативныеОбработчики);
|
||
КонецЕсли;
|
||
НаборРазделенныхОбработчиков.Записать();
|
||
КонецЕсли;
|
||
Если Не ТолькоОтложенные И Не ОбщегоНазначения.РазделениеВключено() Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборНеразделенныхОбработчиков = РегистрыСведений.ОбработчикиОбновленияОбщихДанных.СоздатьНаборЗаписей();
|
||
НаборНеразделенныхОбработчиков.Записать();
|
||
КонецЕсли;
|
||
// АПК:1327-вкл
|
||
|
||
ОписанияБиблиотек = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем().ПоИменам;
|
||
ГруппаОбновления = 1;
|
||
ТекущийРежимВыполнения = "";
|
||
ТекстОшибок = "";
|
||
ДобавленныеОбработчики = Новый Массив;
|
||
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
|
||
|
||
Если Не ТолькоМонопольные И ЗаполнитьВерсииПодсистем Тогда
|
||
СохраненнаяВерсия = ВерсииПодсистемНаНачалоОбновления[ИтерацияОбновления.Подсистема];
|
||
Если СохраненнаяВерсия = Неопределено Тогда
|
||
ВерсииПодсистемНаНачалоОбновления.Вставить(ИтерацияОбновления.Подсистема, ИтерацияОбновления.ПредыдущаяВерсия);
|
||
Иначе
|
||
Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(СохраненнаяВерсия, ИтерацияОбновления.ПредыдущаяВерсия) > 0 Тогда
|
||
ВерсииПодсистемНаНачалоОбновления.Вставить(ИтерацияОбновления.Подсистема, ИтерацияОбновления.ПредыдущаяВерсия);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
// Добавление монопольных и оперативных обработчиков обновления.
|
||
ИмяБиблиотеки = ИтерацияОбновления.Подсистема;
|
||
Если Не ТолькоОтложенные Тогда
|
||
Если Не ПервыйОбменВРИБ Тогда
|
||
ПредыдущаяВерсия = ИтерацияОбновления.ПредыдущаяВерсия;
|
||
ВерсияМетаданных = ИтерацияОбновления.Версия;
|
||
Если ПустаяСтрока(ВерсияМетаданных) Тогда
|
||
ВерсияМетаданных = "0.0.0.0";
|
||
КонецЕсли;
|
||
|
||
ОбработчикиПоВерсиям = Неопределено;
|
||
Если ПредыдущаяВерсия <> "0.0.0.0"
|
||
И ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
ОбработчикиПоВерсиям = ПолучитьПланОбновления(ИтерацияОбновления.Подсистема, ПредыдущаяВерсия, ВерсияМетаданных);
|
||
КонецЕсли;
|
||
|
||
Если ОбработчикиПоВерсиям = Неопределено Тогда
|
||
ОбработчикиПоВерсиям = ОбработчикиОбновленияВИнтервале(ИтерацияОбновления.Обработчики,
|
||
ПредыдущаяВерсия, ИтерацияОбновления.Версия);
|
||
КонецЕсли;
|
||
|
||
Если ОбработчикиПоВерсиям.Строки.Количество() <> 0 Тогда
|
||
ОбработчикиПоВерсиям.Колонки.Процедура.Имя = "ИмяОбработчика";
|
||
ДобавитьОбработчики(ИмяБиблиотеки, ОбработчикиПоВерсиям.Строки, ДобавленныеОбработчики);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Если ТолькоМонопольные Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
// Добавление отложенных обработчиков обновления.
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
// Обработка сценария получения первого сообщения обмена от подчиненного узла после обновления.
|
||
ПредыдущаяВерсия = ?(ПервыйОбменВРИБ, "1.0.0.0", ИтерацияОбновления.ПредыдущаяВерсия);
|
||
РежимВыполненияОтложенныхОбработчиков = ОписанияБиблиотек[ИмяБиблиотеки].РежимВыполненияОтложенныхОбработчиков;
|
||
ПараллельноСВерсии = ОписанияБиблиотек[ИмяБиблиотеки].ПараллельноеОтложенноеОбновлениеСВерсии;
|
||
Если ПервыйОбменВРИБ И РежимВыполненияОтложенныхОбработчиков = "Последовательно" Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ПараметрыОтбора = ПараметрыОтбораОбработчиков();
|
||
ПараметрыОтбора.ПолучатьРазделенные = Истина;
|
||
ПараметрыОтбора.РежимОбновления = "Отложенно";
|
||
ПараметрыОтбора.УчитыватьПервыйОбменВРИБ = (РежимВыполненияОтложенныхОбработчиков = "Параллельно");
|
||
ПараметрыОтбора.ПервыйОбменВРИБ = ПервыйОбменВРИБ;
|
||
|
||
ОбработчикиПоВерсиям = ОбработчикиОбновленияВИнтервале(ИтерацияОбновления.Обработчики,
|
||
ПредыдущаяВерсия, ИтерацияОбновления.Версия, ПараметрыОтбора);
|
||
ОбработчикиПоВерсиям.Колонки.Процедура.Имя = "ИмяОбработчика";
|
||
ДобавитьНезавершенныеОтложенныеОбработчики(
|
||
ИтерацияОбновления,
|
||
ИмяБиблиотеки,
|
||
НезавершенныеОтложенныеОбработчики,
|
||
ОбработчикиПоВерсиям.Строки);
|
||
|
||
Если ПервыйОбменВРИБ Тогда
|
||
УдаляемыеСтроки = Новый Массив;
|
||
Для Каждого СтрокаВерсия Из ОбработчикиПоВерсиям.Строки Цикл
|
||
Если СтрокаВерсия.Версия = "*"
|
||
Или (ЗначениеЗаполнено(ПараллельноСВерсии)
|
||
И ОбщегоНазначенияКлиентСервер.СравнитьВерсии(СтрокаВерсия.Версия, ПараллельноСВерсии) < 0) Тогда
|
||
УдаляемыеСтроки.Добавить(СтрокаВерсия);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Для Каждого УдаляемаяСтрока Из УдаляемыеСтроки Цикл
|
||
ОбработчикиПоВерсиям.Строки.Удалить(УдаляемаяСтрока);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Если ОбработчикиПоВерсиям.Строки.Количество() = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
УпорядочитьВерсииОбработчиков(ОбработчикиПоВерсиям);
|
||
|
||
ДобавитьОтложенныеОбработчики(ИмяБиблиотеки, ОбработчикиПоВерсиям.Строки, ГруппаОбновления, ТекстОшибок, ТекущийРежимВыполнения);
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
Если ЗначениеЗаполнено(ТекстОшибок) Тогда
|
||
ВызватьИсключение ТекстОшибок;
|
||
КонецЕсли;
|
||
|
||
Если Не ТолькоМонопольные И ЗаполнитьВерсииПодсистем Тогда
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
СведенияОбОбновлении.ВерсииПодсистемНаНачалоОбновления = ВерсииПодсистемНаНачалоОбновления;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
КонецЕсли;
|
||
|
||
ЗафиксироватьТранзакцию();
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
КонецПроцедуры
|
||
|
||
// АПК:581-вкл
|
||
|
||
// Вызывается для включения и отключении отложенного обновления.
|
||
//
|
||
// Параметры:
|
||
// Использование - Булево - Истина, если задание нужно включить, иначе Ложь.
|
||
//
|
||
Процедура ПриВключенииОтложенногоОбновления(Использование) Экспорт
|
||
|
||
ОтборЗаданий = Новый Структура;
|
||
ОтборЗаданий.Вставить("Метаданные", Метаданные.РегламентныеЗадания.ОтложенноеОбновлениеИБ);
|
||
Задания = РегламентныеЗаданияСервер.НайтиЗадания(ОтборЗаданий);
|
||
|
||
Для Каждого Задание Из Задания Цикл
|
||
Если Задание.Использование = Использование Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ПараметрыЗадания = Новый Структура("Использование", Использование);
|
||
|
||
ТребуетсяУстановитьЗапланированныйМоментЗапуска = Ложь;
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
|
||
МодульТехнологияСервиса = ОбщегоНазначения.ОбщийМодуль("ТехнологияСервиса");
|
||
ВерсияБиблиотекиБТС = МодульТехнологияСервиса.ВерсияБиблиотеки();
|
||
ТребуетсяУстановитьЗапланированныйМоментЗапуска = ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияБиблиотекиБТС, "2.0.1.0") > 0;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса")
|
||
И Использование
|
||
И ТребуетсяУстановитьЗапланированныйМоментЗапуска Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
ЗапланированныйМоментЗапуска = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ЗапланированныйМоментЗапускаОбновленияОбласти();
|
||
ПараметрыЗадания.Вставить("ЗапланированныйМоментЗапуска", ЗапланированныйМоментЗапуска);
|
||
КонецЕсли;
|
||
|
||
РегламентныеЗаданияСервер.ИзменитьЗадание(Задание.УникальныйИдентификатор, ПараметрыЗадания);
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Выполняет оперативные и монопольные обработчики обновления
|
||
// по переданной итерации обновления.
|
||
//
|
||
Функция ВыполнитьИтерациюОбновления(Знач ИтерацияОбновления, Знач Параметры) Экспорт
|
||
|
||
ИдентификаторБиблиотеки = ИтерацияОбновления.Подсистема;
|
||
ВерсияМетаданныхИБ = ИтерацияОбновления.Версия;
|
||
ОбработчикиОбновления = ИтерацияОбновления.Обработчики;
|
||
|
||
ТекущаяВерсияИБ = ИтерацияОбновления.ПредыдущаяВерсия;
|
||
|
||
НоваяВерсияИБ = ТекущаяВерсияИБ;
|
||
ВерсияМетаданных = ВерсияМетаданныхИБ;
|
||
Если ПустаяСтрока(ВерсияМетаданных) Тогда
|
||
ВерсияМетаданных = "0.0.0.0";
|
||
КонецЕсли;
|
||
|
||
Если ТекущаяВерсияИБ <> "0.0.0.0"
|
||
И ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
// Получение списка обработчиков сформированного на этапе выполнения неразделенных обработчиков.
|
||
ВыполняемыеОбработчики = ПолучитьПланОбновления(ИдентификаторБиблиотеки, ТекущаяВерсияИБ, ВерсияМетаданных);
|
||
Если ВыполняемыеОбработчики = Неопределено Тогда
|
||
Если ИтерацияОбновления.ЭтоОсновнаяКонфигурация Тогда
|
||
ШаблонСообщения = НСтр("ru = 'Не существует план обновления конфигурации %1 с версии %2 на версию %3'");
|
||
Иначе
|
||
ШаблонСообщения = НСтр("ru = 'Не существует план обновления библиотеки %1 с версии %2 на версию %3'");
|
||
КонецЕсли;
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонСообщения, ИдентификаторБиблиотеки, ТекущаяВерсияИБ, ВерсияМетаданных);
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
ВыполняемыеОбработчики = ОбработчикиОбновленияВИнтервале(ОбработчикиОбновления, ТекущаяВерсияИБ, ВерсияМетаданных);
|
||
КонецЕсли;
|
||
Иначе
|
||
ВыполняемыеОбработчики = ОбработчикиОбновленияВИнтервале(ОбработчикиОбновления, ТекущаяВерсияИБ, ВерсияМетаданных);
|
||
КонецЕсли;
|
||
|
||
ОбязательныеРазделенныеОбработчики = ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления();
|
||
ИсходнаяВерсияИБ = ТекущаяВерсияИБ;
|
||
ЗаписыватьВЖурнал = Константы.ДетализироватьОбновлениеИБВЖурналеРегистрации.Получить();
|
||
|
||
Для Каждого Версия Из ВыполняемыеОбработчики.Строки Цикл
|
||
|
||
Если Версия.Версия = "*" Тогда
|
||
Сообщение = НСтр("ru = 'Выполняются обязательные процедуры обновления информационной базы.'");
|
||
Иначе
|
||
НоваяВерсияИБ = Версия.Версия;
|
||
Если ТекущаяВерсияИБ = "0.0.0.0" Тогда
|
||
Сообщение = НСтр("ru = 'Выполняется начальное заполнение данных.'");
|
||
ИначеЕсли ИтерацияОбновления.ЭтоОсновнаяКонфигурация Тогда
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Выполняется обновление информационной базы с версии %1 на версию %2.'"),
|
||
ТекущаяВерсияИБ, НоваяВерсияИБ);
|
||
Иначе
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Выполняется обновление данных библиотеки %3 с версии %1 на версию %2.'"),
|
||
ТекущаяВерсияИБ, НоваяВерсияИБ, ИдентификаторБиблиотеки);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
Для Каждого Обработчик Из Версия.Строки Цикл
|
||
|
||
ПараметрыОбработчика = Неопределено;
|
||
Если Обработчик.ВерсияРегистрации = "*" Тогда
|
||
|
||
Если Обработчик.УправлениеОбработчиками Тогда
|
||
ПараметрыОбработчика = Новый Структура;
|
||
ПараметрыОбработчика.Вставить("РазделенныеОбработчики", ОбязательныеРазделенныеОбработчики);
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.МонопольныйРежим = Истина Или Обработчик.РежимВыполнения = "Монопольно" Тогда
|
||
Если Параметры.ОперативноеОбновление Тогда
|
||
// Проверки выполняются в ВозможноОперативноеОбновление, а само обновление для таких
|
||
// обработчиков выполняется только при неоперативном обновлении.
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыОбработчика = Неопределено Тогда
|
||
ПараметрыОбработчика = Новый Структура;
|
||
КонецЕсли;
|
||
ПараметрыОбработчика.Вставить("МонопольныйРежим", Истина);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ДополнительныеПараметры = Новый Структура;
|
||
ДополнительныеПараметры.Вставить("ЗаписыватьВЖурнал", ЗаписыватьВЖурнал);
|
||
ДополнительныеПараметры.Вставить("ИдентификаторБиблиотеки", ИдентификаторБиблиотеки);
|
||
ДополнительныеПараметры.Вставить("ХодВыполненияОбработчиков", Параметры.ХодВыполненияОбработчиков);
|
||
ДополнительныеПараметры.Вставить("ВФоне", Параметры.ВФоне);
|
||
|
||
ВыполнитьОбработчикОбновления(Обработчик, ПараметрыОбработчика, ДополнительныеПараметры);
|
||
КонецЦикла;
|
||
|
||
Если Версия.Версия = "*" Тогда
|
||
Сообщение = НСтр("ru = 'Выполнены обязательные процедуры обновления информационной базы.'");
|
||
ИначеЕсли СтрНачинаетсяС(Версия.Версия, "ОтладкаОбработчика") Тогда
|
||
Сообщение = НСтр("ru = 'Выполнены отлаживаемые процедуры обновления информационной базы.'");
|
||
Иначе
|
||
Если ИтерацияОбновления.ЭтоОсновнаяКонфигурация Тогда
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Выполнено обновление информационной базы с версии %1 на версию %2.'"),
|
||
ТекущаяВерсияИБ, НоваяВерсияИБ);
|
||
Иначе
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Выполнено обновление данных библиотеки %3 с версии %1 на версию %2.'"),
|
||
ТекущаяВерсияИБ, НоваяВерсияИБ, ИдентификаторБиблиотеки);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
Если Версия.Версия <> "*" И Не СтрНачинаетсяС(Версия.Версия, "ОтладкаОбработчика") Тогда
|
||
// Установка номера версии информационной базы.
|
||
УстановитьВерсиюИБ(ИдентификаторБиблиотеки, НоваяВерсияИБ, ИтерацияОбновления.ЭтоОсновнаяКонфигурация);
|
||
ТекущаяВерсияИБ = НоваяВерсияИБ;
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
// Установка номера версии информационной базы.
|
||
ОтметитьРегистрациюДанных = Неопределено;
|
||
Если Параметры.Свойство("ОтметитьРегистрациюДанных") Тогда
|
||
ОтметитьРегистрациюДанных = Параметры.ОтметитьРегистрациюДанных;
|
||
КонецЕсли;
|
||
Если ВерсияИБ(ИдентификаторБиблиотеки) <> ВерсияМетаданныхИБ Тогда
|
||
УстановитьВерсиюИБ(ИдентификаторБиблиотеки, ВерсияМетаданныхИБ, ИтерацияОбновления.ЭтоОсновнаяКонфигурация, ОтметитьРегистрациюДанных);
|
||
КонецЕсли;
|
||
|
||
Если ТекущаяВерсияИБ <> "0.0.0.0" Тогда
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.СформироватьПланОбновленияОбластиДанных(ИдентификаторБиблиотеки, ОбработчикиОбновления,
|
||
ОбязательныеРазделенныеОбработчики, ИсходнаяВерсияИБ, ВерсияМетаданныхИБ);
|
||
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
Возврат ВыполняемыеОбработчики;
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Обработчики событий подсистем конфигурации.
|
||
|
||
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииОбработчиковУстановкиПараметровСеанса.
|
||
Процедура ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) Экспорт
|
||
|
||
Обработчики.Вставить("ВыполняетсяОбновлениеИБ", "ОбновлениеИнформационнойБазыСлужебный.УстановкаПараметровСеанса");
|
||
Обработчики.Вставить("ПараметрыОбработчикаОбновления", "ОбновлениеИнформационнойБазыСлужебный.УстановкаПараметровСеанса");
|
||
Обработчики.Вставить("ОтмененныеДлительныеОперации", "ДлительныеОперации.УстановкаПараметровСеанса");
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок.
|
||
Процедура ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоискаСсылок) Экспорт
|
||
|
||
ИсключенияПоискаСсылок.Добавить(Метаданные.РегистрыСведений.ДанныеОбработанныеВЦентральномУзлеРИБ.ПолноеИмя());
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ЦентрМониторингаПереопределяемый.ПриСбореПоказателейСтатистикиКонфигурации.
|
||
Процедура ПриСбореПоказателейСтатистикиКонфигурации() Экспорт
|
||
|
||
Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЦентрМониторинга") Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
МодульЦентрМониторинга = ОбщегоНазначения.ОбщийМодуль("ЦентрМониторинга");
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
Если СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно <> Истина Тогда
|
||
Возврат; // Получаем сведения только в том случае, когда отложенное обновление успешно завершилось.
|
||
КонецЕсли;
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.ДлительностьОбработки КАК ДлительностьОбработки
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения";
|
||
Обработчики = Запрос.Выполнить().Выгрузить();
|
||
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
МодульЦентрМониторинга.ЗаписатьСтатистикуОбъектаКонфигурации("ВремяВыполненияОтложенногоОбработчика." + Обработчик.ИмяОбработчика, Обработчик.ДлительностьОбработки / 1000);
|
||
КонецЦикла;
|
||
|
||
ВремяНачала = СведенияОбОбновлении.ВремяНачалаОбновления;
|
||
ВремяОкончания = СведенияОбОбновлении.ВремяОкончанияОбновления;
|
||
|
||
Если ЗначениеЗаполнено(ВремяНачала) И ЗначениеЗаполнено(ВремяОкончания) Тогда
|
||
МодульЦентрМониторинга.ЗаписатьСтатистикуОбъектаКонфигурации("ВремяВыполненияОбработчиков",
|
||
ВремяОкончания - ВремяНачала);
|
||
КонецЕсли;
|
||
|
||
ВремяНачала = СведенияОбОбновлении.ВремяНачалаОтложенногоОбновления;
|
||
ВремяОкончания = СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления;
|
||
|
||
Если ЗначениеЗаполнено(ВремяНачала) И ЗначениеЗаполнено(ВремяОкончания) Тогда
|
||
МодульЦентрМониторинга.ЗаписатьСтатистикуОбъектаКонфигурации("ВремяВыполненияОтложенныхОбработчиков",
|
||
ВремяОкончания - ВремяНачала);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхПодчиненному.
|
||
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель) Экспорт
|
||
|
||
ПриОтправкеВерсийПодсистем(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза);
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхГлавному.
|
||
Процедура ПриОтправкеДанныхГлавному(ЭлементДанных, ОтправкаЭлемента, Получатель) Экспорт
|
||
|
||
ПриОтправкеВерсийПодсистем(ЭлементДанных, ОтправкаЭлемента);
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииПараметровРаботыКлиентаПриЗапуске.
|
||
Процедура ПриДобавленииПараметровРаботыКлиентаПриЗапуске(Параметры) Экспорт
|
||
|
||
Параметры.Вставить("НачальноеЗаполнениеДанных", РежимОбновленияДанных() = "НачальноеЗаполнение");
|
||
Параметры.Вставить("ПоказатьОписаниеИзмененийСистемы", ПоказатьОписаниеИзмененийСистемы());
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если Пользователи.ЭтоПолноправныйПользователь(, Истина)
|
||
И Не ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы()
|
||
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбновлениеКонфигурации") Тогда
|
||
Значение = ОбщегоНазначения.ХранилищеСистемныхНастроекЗагрузить("ПроверкаПатчей", "НомерВерсии");
|
||
Если Значение = Неопределено
|
||
Или ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Метаданные.Версия, Значение) > 0 Тогда
|
||
МодульОбновлениеКонфигурации = ОбщегоНазначения.ОбщийМодуль("ОбновлениеКонфигурации");
|
||
Результат = МодульОбновлениеКонфигурации.ИсправленияИзменены();
|
||
ОбщегоНазначения.ХранилищеСистемныхНастроекСохранить("ПроверкаПатчей", "НомерВерсии", Метаданные.Версия);
|
||
Если Результат.ЕстьИзменения Тогда
|
||
Сведения = СведенияОбОбновленииИнформационнойБазы();
|
||
Сведения.ВерсияУдалениеПатчей = Метаданные.Версия;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(Сведения);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
СтатусОбработчиков = СтатусНевыполненныхОбработчиков();
|
||
Если СтатусОбработчиков = "" Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
Если СтатусОбработчиков = "СтатусОшибка"
|
||
И Пользователи.ЭтоПолноправныйПользователь(, Истина) Тогда
|
||
Параметры.Вставить("ПоказатьСообщениеОбОшибочныхОбработчиках");
|
||
Иначе
|
||
Параметры.Вставить("ПоказатьОповещениеОНевыполненныхОбработчиках");
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковОбновления.
|
||
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПроверкаЛегальностиПолученияОбновления") Тогда
|
||
Обработчик = Обработчики.Добавить();
|
||
Обработчик.НачальноеЗаполнение = Истина;
|
||
Обработчик.Процедура = "ОбновлениеИнформационнойБазыСлужебный.ЗаписатьПодтверждениеЛегальностиПолученияОбновлений";
|
||
КонецЕсли;
|
||
|
||
Если Не ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Обработчик = Обработчики.Добавить();
|
||
Обработчик.Версия = "3.0.2.160";
|
||
Обработчик.Процедура = "ОбновлениеИнформационнойБазыСлужебный.УстановитьКлючРегламентногоЗадания";
|
||
Обработчик.РежимВыполнения = "Оперативно";
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ОчередьЗаданийПереопределяемый.ПриПолученииСпискаШаблонов.
|
||
Процедура ПриПолученииСпискаШаблонов(ШаблоныЗаданий) Экспорт
|
||
|
||
ШаблоныЗаданий.Добавить("ОтложенноеОбновлениеИБ");
|
||
|
||
КонецПроцедуры
|
||
|
||
// Параметры:
|
||
// ТекущиеДела - см. ТекущиеДелаСервер.ТекущиеДела.
|
||
//
|
||
Процедура ПриЗаполненииСпискаТекущихДел(ТекущиеДела) Экспорт
|
||
|
||
МодульТекущиеДелаСервер = ОбщегоНазначения.ОбщийМодуль("ТекущиеДелаСервер");
|
||
Если Не Пользователи.ЭтоПолноправныйПользователь(, Истина)
|
||
Или МодульТекущиеДелаСервер.ДелоОтключено("ОтложенноеОбновление") Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
// Процедура вызывается только при наличии подсистемы "Текущие дела", поэтому здесь
|
||
// не делается проверка существования подсистемы.
|
||
Разделы = МодульТекущиеДелаСервер.РазделыДляОбъекта(Метаданные.Обработки.РезультатыОбновленияПрограммы.ПолноеИмя());
|
||
|
||
СтатусОбработчиков = СтатусНевыполненныхОбработчиков();
|
||
ЕстьОбработчикиСОшибкой = (СтатусОбработчиков = "СтатусОшибка");
|
||
ЕстьНеВыполненныеОбработчики = (СтатусОбработчиков = "СтатусНеВыполнено");
|
||
ЕстьПриостановленныеОбработчики = (СтатусОбработчиков = "СтатусПриостановлен");
|
||
|
||
Для Каждого Раздел Из Разделы Цикл
|
||
Идентификатор = "ОтложенноеОбновление" + СтрЗаменить(Раздел.ПолноеИмя(), ".", "");
|
||
Дело = ТекущиеДела.Добавить();
|
||
Дело.Идентификатор = Идентификатор;
|
||
Дело.ЕстьДела = (ЕстьОбработчикиСОшибкой Или ЕстьНеВыполненныеОбработчики Или ЕстьПриостановленныеОбработчики);
|
||
Дело.Важное = ЕстьОбработчикиСОшибкой;
|
||
Дело.Представление = НСтр("ru = 'Обновление программы не завершено'");
|
||
Дело.Форма = "Обработка.РезультатыОбновленияПрограммы.Форма.РезультатыОбновленияПрограммы";
|
||
Дело.Владелец = Раздел;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ВариантыОтчетовПереопределяемый.НастроитьВариантыОтчетов.
|
||
Процедура ПриНастройкеВариантовОтчетов(Настройки) Экспорт
|
||
МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
|
||
МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ПрогрессОтложенногоОбновления);
|
||
КонецПроцедуры
|
||
|
||
// Перезапускает отложенные обработчики, выполняющиеся только в главном узле
|
||
// при получении первого сообщения обмена.
|
||
//
|
||
Процедура ПриПолученииПервогоСообщенияОбменаРИБПослеОбновления() Экспорт
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
ИнформационнаяБазаФайловая = ОбщегоНазначения.ИнформационнаяБазаФайловая();
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
Если СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно = Неопределено
|
||
И Не ИнформационнаяБазаФайловая Тогда
|
||
ОтключитьОтложенноеОбновление();
|
||
ПараметрыОтбора = Новый Структура;
|
||
ПараметрыОтбора.Вставить("ИмяМетода", "ОбновлениеИнформационнойБазыСлужебный.ВыполнитьОтложенноеОбновление");
|
||
ПараметрыОтбора.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
|
||
МассивФоновыхЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(ПараметрыОтбора);
|
||
Если МассивФоновыхЗаданий.Количество() = 1 Тогда
|
||
ФоновоеЗадание = МассивФоновыхЗаданий[0];
|
||
ФоновоеЗадание.Отменить();
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ИтерацииОбновления = ИтерацииОбновления();
|
||
Обработки.ОписаниеОбработчиковОбновления.ЗаполнитьНомерОчереди(ИтерацииОбновления);
|
||
ОбновитьСписокВыполняемыхОбработчиковОбновления(ИтерацииОбновления, Истина);
|
||
ПеререгистрироватьДанныеДляОтложенногоОбновления();
|
||
Если ИнформационнаяБазаФайловая Тогда
|
||
ВыполнитьОтложенноеОбновлениеСейчас();
|
||
Иначе
|
||
ЗапланироватьОтложенноеОбновление();
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Вызывается при выполнении скрипта обновления из процедуры ОбновлениеКонфигурации.ЗавершитьОбновление.
|
||
Процедура ПослеЗавершенияОбновления() Экспорт
|
||
|
||
ЗаписатьПодтверждениеЛегальностиПолученияОбновлений();
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ВыгрузкаЗагрузкаДанныхПереопределяемый.ПослеЗагрузкиДанных.
|
||
Процедура ПослеЗагрузкиДанных(Контейнер) Экспорт
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
|
||
Если СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно <> Истина Тогда
|
||
ЗапланироватьОтложенноеОбновление();
|
||
КонецЕсли;
|
||
КонецПроцедуры
|
||
|
||
// См. ПодключаемыеКомандыПереопределяемый.ПриОпределенииКомандПодключенныхКОбъекту
|
||
Процедура ПриОпределенииКомандПодключенныхКОбъекту(НастройкиФормы, Источники, ПодключенныеОтчетыИОбработки, Команды) Экспорт
|
||
|
||
Команда = Команды.Добавить();
|
||
Команда.Вид = "ОбновлениеВерсииИБ";
|
||
Команда.Представление = НСтр("ru = 'Разблокировать объект для редактирования'");
|
||
Команда.РежимЗаписи = "НеЗаписывать";
|
||
Команда.Назначение = "ДляОбъекта";
|
||
Команда.ТолькоВоВсехДействиях = Истина;
|
||
Команда.Обработчик = "ОбновлениеИнформационнойБазыКлиент.РазблокироватьОбъектДляРедактирования";
|
||
|
||
МодульПодключаемыеКоманды = ОбщегоНазначения.ОбщийМодуль("ПодключаемыеКоманды");
|
||
МодульПодключаемыеКоманды.ДобавитьУсловиеВидимостиКоманды(Команда, "ОбновлениеВерсииИБ_ОбъектЗаблокирован");
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ПодключаемыеКомандыПереопределяемый.ПриОпределенииВидовПодключаемыхКоманд
|
||
Процедура ПриОпределенииВидовПодключаемыхКоманд(ВидыПодключаемыхКоманд) Экспорт
|
||
|
||
Вид = ВидыПодключаемыхКоманд.Добавить();
|
||
Вид.Имя = "ОбновлениеВерсииИБ";
|
||
Вид.Заголовок = НСтр("ru = 'Разблокировка объекта'");
|
||
Вид.Отображение = ОтображениеКнопки.КартинкаИТекст;
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. ОчередьЗаданийПереопределяемый.ПриОпределенииПсевдонимовОбработчиков.
|
||
Процедура ПриОпределенииПсевдонимовОбработчиков(СоответствиеИменПсевдонимам) Экспорт
|
||
|
||
СоответствиеИменПсевдонимам.Вставить("ОбновлениеИнформационнойБазы.ПерезапуститьОтложенноеОбновление");
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. КонтрольВеденияУчетаПереопределяемый.ПриОпределенииПроверок.
|
||
Процедура ПриОпределенииПроверок(ГруппыПроверок, Проверки) Экспорт
|
||
|
||
Проверка = Проверки.Добавить();
|
||
Проверка.ИдентификаторГруппы = "СистемныеПроверки";
|
||
Проверка.Наименование = НСтр("ru = 'Проблема с данными при обновлении на новую версию'");
|
||
Проверка.Причины = НСтр("ru = 'Некорректная синхронизация данных с другими программами или импорт данных,
|
||
|ошибки в сторонних инструментах (например, внешних обработках или расширениях) или сбои в работе оборудования.'");
|
||
Проверка.Рекомендация = НСтр("ru = 'Если не заполнены обязательные реквизиты, то заполнить их вручную.
|
||
|Восстановить отсутствующие данные из резервной копии.'");
|
||
Проверка.Идентификатор = "ОбновлениеИнформационнойБазыПроблемаСДанными";
|
||
Проверка.ОбработчикПроверки = "ОбновлениеИнформационнойБазыСлужебный.ОбработчикПроверкиВеденияУчета";
|
||
Проверка.ЗапрещеноИзменениеВажности = Ложь;
|
||
Проверка.КонтекстПроверокВеденияУчета = "ОбновлениеВерсииИБ";
|
||
Проверка.Отключена = Истина;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция НастройкиПодсистемы() Экспорт
|
||
|
||
ПараметрыСообщенияОНевыполненныхОтложенныхОбработчиках = Новый Структура;
|
||
ПараметрыСообщенияОНевыполненныхОтложенныхОбработчиках.Вставить("ТекстСообщения", "");
|
||
ПараметрыСообщенияОНевыполненныхОтложенныхОбработчиках.Вставить("КартинкаСообщения", Неопределено);
|
||
ПараметрыСообщенияОНевыполненныхОтложенныхОбработчиках.Вставить("ЗапрещатьПродолжение", Ложь);
|
||
|
||
|
||
Настройки = Новый Структура;
|
||
Настройки.Вставить("ПоясненияДляРезультатовОбновления", "");
|
||
Настройки.Вставить("РасположениеОписанияИзмененийПрограммы", "");
|
||
Настройки.Вставить("ПараметрыСообщенияОНевыполненныхОтложенныхОбработчиках", ПараметрыСообщенияОНевыполненныхОтложенныхОбработчиках);
|
||
Настройки.Вставить("МногопоточноеОбновление", Ложь);
|
||
Настройки.Вставить("КоличествоПотоковОбновленияИнформационнойБазыПоУмолчанию", 1);
|
||
|
||
Настройки.Вставить("ОбъектыСНачальнымЗаполнением", Новый Массив);
|
||
ИнтеграцияПодсистемБСП.ПриОпределенииОбъектовСНачальнымЗаполнением(Настройки.ОбъектыСНачальнымЗаполнением);
|
||
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек(Настройки);
|
||
|
||
Возврат Настройки;
|
||
|
||
КонецФункции
|
||
|
||
// Начальное заполнение предопределенных данных
|
||
|
||
// Возвращаемое значение:
|
||
// Массив из ОбъектМетаданных
|
||
//
|
||
Функция ОбъектыСНачальнымЗаполнением() Экспорт
|
||
|
||
НастройкиПодсистемы = НастройкиПодсистемы();
|
||
ОбъектыСНачальнымЗаполнением = НастройкиПодсистемы.ОбъектыСНачальнымЗаполнением;
|
||
Возврат ОбъектыСНачальнымЗаполнением;
|
||
|
||
КонецФункции
|
||
|
||
Функция НастройкиПредопределенныхЭлементов(МенеджерОбъекта, ПредопределенныеДанные) Экспорт
|
||
|
||
ПользовательскиеНастройкиЗаполненияЭлементов = ПользовательскиеНастройкиЗаполненияЭлементов();
|
||
ПользовательскиеНастройкиЗаполненияЭлементов.ДополнительныеПараметры.Вставить("ПредопределенныеДанные", ПредопределенныеДанные);
|
||
|
||
ПолноеИмяОбъекта = МенеджерОбъекта.ПустаяСсылка().Метаданные().ПолноеИмя();
|
||
|
||
МенеджерОбъекта.ПриНастройкеНачальногоЗаполненияЭлементов(ПользовательскиеНастройкиЗаполненияЭлементов);
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПриНастройкеНачальногоЗаполненияЭлементов(ПолноеИмяОбъекта,
|
||
ПользовательскиеНастройкиЗаполненияЭлементов);
|
||
|
||
НастройкиЗаполненияЭлементов = НастройкиЗаполненияЭлементов();
|
||
ЗаполнитьЗначенияСвойств(НастройкиЗаполненияЭлементов.ПереопределяемыеНастройки, ПользовательскиеНастройкиЗаполненияЭлементов);
|
||
|
||
НастройкиЗаполненияЭлементов.ЕстьКолонкаИмяПредопределенныхДанных =
|
||
ПредопределенныеДанные.Колонки.Найти("ИмяПредопределенныхДанных") <> Неопределено;
|
||
|
||
НастройкиЗаполненияЭлементов.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита =
|
||
?(ЗначениеЗаполнено(НастройкиЗаполненияЭлементов.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита),
|
||
НастройкиЗаполненияЭлементов.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита, "ИмяПредопределенныхДанных");
|
||
|
||
Возврат НастройкиЗаполненияЭлементов;
|
||
|
||
КонецФункции
|
||
|
||
// Описание настроек заполнения элементов
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ПереопределяемыеНастройки - см. ПользовательскиеНастройкиЗаполненияЭлементов
|
||
// * ЕстьКолонкаИмяПредопределенныхДанных - Булево
|
||
//
|
||
Функция НастройкиЗаполненияЭлементов() Экспорт
|
||
|
||
НастройкиЗаполненияЭлементов = Новый Структура;
|
||
НастройкиЗаполненияЭлементов.Вставить("ПереопределяемыеНастройки", ПользовательскиеНастройкиЗаполненияЭлементов());
|
||
НастройкиЗаполненияЭлементов.Вставить("ЕстьКолонкаИмяПредопределенныхДанных", Ложь);
|
||
|
||
Возврат НастройкиЗаполненияЭлементов;
|
||
|
||
КонецФункции
|
||
|
||
Функция ПредопределенныеДанныеОбъекта(Знач МетаданныеОбъекта, МенеджерОбъекта, ЛокализуемыеРеквизитыОбъекта) Экспорт
|
||
|
||
Языки = СтандартныеПодсистемыСервер.ЯзыкиКонфигурации();
|
||
|
||
// Таблица с предопределенными данными
|
||
ПредопределенныеДанные = Новый ТаблицаЗначений;
|
||
ТабличныеЧасти = Новый Структура;
|
||
|
||
Для Каждого Реквизит Из МетаданныеОбъекта.СтандартныеРеквизиты Цикл
|
||
ДобавитьКолонкуТаблицыПредопределенныхДанных(ПредопределенныеДанные, Реквизит, ЛокализуемыеРеквизитыОбъекта, Языки);
|
||
КонецЦикла;
|
||
|
||
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
|
||
ДобавитьКолонкуТаблицыПредопределенныхДанных(ПредопределенныеДанные, Реквизит, ЛокализуемыеРеквизитыОбъекта, Языки);
|
||
КонецЦикла;
|
||
|
||
Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл
|
||
|
||
ПредопределенныеДанные.Колонки.Добавить(ТабличнаяЧасть.Имя, Новый ОписаниеТипов("ТаблицаЗначений"));
|
||
Таблица = Новый ТаблицаЗначений;
|
||
Для Каждого Реквизит Из ТабличнаяЧасть.СтандартныеРеквизиты Цикл
|
||
ДобавитьКолонкуТаблицыПредопределенныхДанных(Таблица, Реквизит, ЛокализуемыеРеквизитыОбъекта, Языки);
|
||
КонецЦикла;
|
||
|
||
Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл
|
||
ДобавитьКолонкуТаблицыПредопределенныхДанных(Таблица, Реквизит, ЛокализуемыеРеквизитыОбъекта, Языки);
|
||
КонецЦикла;
|
||
ТабличныеЧасти.Вставить(ТабличнаяЧасть.Имя, Таблица);
|
||
|
||
КонецЦикла;
|
||
|
||
Если ОбщегоНазначения.ЭтоПланСчетов(МетаданныеОбъекта)
|
||
Или ОбщегоНазначения.ЭтоПланВидовРасчета(МетаданныеОбъекта) Тогда
|
||
Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.СтандартныеТабличныеЧасти Цикл
|
||
|
||
ПредопределенныеДанные.Колонки.Добавить(ТабличнаяЧасть.Имя, Новый ОписаниеТипов("ТаблицаЗначений"));
|
||
Таблица = Новый ТаблицаЗначений;
|
||
Для Каждого Реквизит Из ТабличнаяЧасть.СтандартныеРеквизиты Цикл
|
||
ДобавитьКолонкуТаблицыПредопределенныхДанных(Таблица, Реквизит, ЛокализуемыеРеквизитыОбъекта, Языки);
|
||
КонецЦикла;
|
||
|
||
ТабличныеЧасти.Вставить(ТабличнаяЧасть.Имя, Таблица);
|
||
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Если ПредопределенныеДанные.Колонки.Найти("ИмяПредопределенныхДанных") <> Неопределено Тогда
|
||
ПредопределенныеДанные.Индексы.Добавить("ИмяПредопределенныхДанных");
|
||
КонецЕсли;
|
||
|
||
МенеджерОбъекта.ПриНачальномЗаполненииЭлементов(Языки, ПредопределенныеДанные, ТабличныеЧасти);
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПриНачальномЗаполненииЭлементов(МетаданныеОбъекта.ПолноеИмя(), Языки, ПредопределенныеДанные, ТабличныеЧасти);
|
||
|
||
Если ПредопределенныеДанные.Колонки.Найти("Ссылка") <> Неопределено Тогда
|
||
Для Каждого СтрокаПредопределенныхДанных Из ПредопределенныеДанные Цикл
|
||
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
Если ТипЗнч(СтрокаПредопределенныхДанных.Ссылка) = Тип("УникальныйИдентификатор") Тогда
|
||
СтрокаПредопределенныхДанных.Ссылка = МенеджерОбъекта.ПолучитьСсылку(СтрокаПредопределенныхДанных.Ссылка);
|
||
ИначеЕсли ТипЗнч(СтрокаПредопределенныхДанных.Ссылка) = Тип("Строка") Тогда
|
||
СтрокаПредопределенныхДанных.Ссылка = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаПредопределенныхДанных.Ссылка));
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Возврат ПредопределенныеДанные;
|
||
|
||
КонецФункции
|
||
|
||
// Параметры:
|
||
// ОбновитьМультиязычныеСтроки - Булево - если Истина, то будут перезаполнены, только мультиязычные реквизиты.
|
||
// ДополнительныеПараметры - см. МультиязычностьСервер.ОписаниеСтарыхИНовыхНастроекЯзыков
|
||
//
|
||
Процедура НачальноеЗаполнениеПредопределенныхДанных(ОбновитьМультиязычныеСтроки = Ложь, ДополнительныеПараметры = Неопределено) Экспорт
|
||
|
||
ОбъектыСНачальнымЗаполнением = ОбъектыСНачальнымЗаполнением();
|
||
ПараметрыЗаполнения = Новый Структура;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
МодульМультиязычностьСервер.ПриПолученииПараметровЗаполненияПредопределенныхДанных(ПараметрыЗаполнения);
|
||
КонецЕсли;
|
||
|
||
ПроверятьНеобходимостьВыполнения = ДополнительныеПараметры <> Неопределено
|
||
И ТипЗнч(ДополнительныеПараметры) = Тип("Структура")
|
||
И ДополнительныеПараметры.Свойство("НовыеОбъекты");
|
||
|
||
Для Каждого МетаданныеОбъекта Из ОбъектыСНачальнымЗаполнением Цикл
|
||
|
||
Если ПроверятьНеобходимостьВыполнения
|
||
И ДополнительныеПараметры.НовыеОбъекты.Найти(МетаданныеОбъекта.ПолноеИмя()) = Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ПараметрыЗаполнения = НаборПараметровДляЗаполненияОбъекта(МетаданныеОбъекта);
|
||
|
||
МенеджерОбъекта = ПараметрыЗаполнения.МенеджерОбъекта;
|
||
ПредопределенныеДанные = ПараметрыЗаполнения.ПредопределенныеДанные;
|
||
НастройкиЗаполнения = ПараметрыЗаполнения.НастройкиПредопределенныхЭлементов;
|
||
|
||
ИмяКлючевогоРеквизита = НастройкиЗаполнения.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита;
|
||
|
||
СуществующиеЭлементы = СуществующиеПоставляемыеЭлементы(ПредопределенныеДанные, НастройкиЗаполнения, МенеджерОбъекта, МетаданныеОбъекта);
|
||
|
||
ТабличныеЧасти = Новый Массив;
|
||
ОбъектМетаданныхТабличныеЧасти = МетаданныеОбъекта.ТабличныеЧасти; // КоллекцияОбъектовМетаданных из ОбъектМетаданныхТабличнаяЧасть
|
||
Для Каждого ТабличнаяЧасть Из ОбъектМетаданныхТабличныеЧасти Цикл
|
||
Если ПредопределенныеДанные.Колонки.Найти(ТабличнаяЧасть.Имя) <> Неопределено Тогда
|
||
ТабличныеЧасти.Добавить(ТабличнаяЧасть.Имя);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
РеквизитыИсключения = Новый Соответствие;
|
||
Если СтрНачинаетсяС(МетаданныеОбъекта.ПолноеИмя(), "ПланВидовХарактеристик") Тогда
|
||
РеквизитыИсключения.Вставить("ТипЗначения", Истина);
|
||
КонецЕсли;
|
||
|
||
ПоддерживаетсяИерархия = ПредопределенныеДанные.Колонки.Найти("ЭтоГруппа") <> Неопределено;
|
||
РеквизитыИсключения.Вставить("Родитель", Истина); // Поле заполняется отдельно
|
||
|
||
РеквизитыИсключенияСЭлементами = Новый Соответствие;
|
||
Если ПоддерживаетсяИерархия Тогда
|
||
ОбщегоНазначенияКлиентСервер.ДополнитьСоответствие(РеквизитыИсключенияСЭлементами, РеквизитыИсключения);
|
||
ДляЭлемента = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляЭлемента;
|
||
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
|
||
Если Реквизит.Использование = ДляЭлемента Тогда
|
||
РеквизитыИсключенияСЭлементами.Вставить(Реквизит.Имя, Истина);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
ЕстьКолонкаСсылка = ПредопределенныеДанные.Колонки.Найти("Ссылка") <> Неопределено;
|
||
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
|
||
Для каждого СтрокаТаблицы Из ПредопределенныеДанные Цикл
|
||
|
||
СсылкаНаОбъект = Неопределено;
|
||
|
||
Если НастройкиЗаполнения.ЕстьКолонкаИмяПредопределенныхДанных Тогда
|
||
СсылкаНаОбъект = СуществующиеЭлементы[СтрокаТаблицы.ИмяПредопределенныхДанных];
|
||
КонецЕсли;
|
||
|
||
Если СсылкаНаОбъект = Неопределено И ЗначениеЗаполнено(СтрокаТаблицы[ИмяКлючевогоРеквизита]) Тогда
|
||
СсылкаНаОбъект = СуществующиеЭлементы[СтрокаТаблицы[ИмяКлючевогоРеквизита]];
|
||
КонецЕсли;
|
||
|
||
Если СсылкаНаОбъект <> Неопределено Тогда
|
||
|
||
БлокировкаДанных = Новый БлокировкаДанных;
|
||
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(МетаданныеОбъекта.ПолноеИмя());
|
||
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкаНаОбъект);
|
||
БлокировкаДанных.Заблокировать();
|
||
|
||
ЗаполняемыйЭлемент = СсылкаНаОбъект.ПолучитьОбъект();
|
||
|
||
Иначе
|
||
|
||
Если ПоддерживаетсяИерархия И СтрокаТаблицы.ЭтоГруппа = Истина Тогда
|
||
ЗаполняемыйЭлемент = МенеджерОбъекта.СоздатьГруппу();
|
||
Иначе
|
||
ЗаполняемыйЭлемент = МенеджерОбъекта.СоздатьЭлемент();
|
||
КонецЕсли;
|
||
|
||
Если ЕстьКолонкаСсылка И ЗначениеЗаполнено(СтрокаТаблицы.Ссылка) Тогда
|
||
|
||
ЗаполняемыйЭлемент.УстановитьСсылкуНового(СтрокаТаблицы.Ссылка);
|
||
|
||
Если ЗначениеЗаполнено(СтрокаТаблицы[ИмяКлючевогоРеквизита]) Тогда
|
||
СуществующиеЭлементы.Вставить(СтрокаТаблицы[ИмяКлючевогоРеквизита], СтрокаТаблицы.Ссылка);
|
||
КонецЕсли;
|
||
|
||
Иначе
|
||
|
||
НоваяСсылка = МенеджерОбъекта.ПолучитьСсылку();
|
||
ЗаполняемыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);
|
||
|
||
Если ЗначениеЗаполнено(СтрокаТаблицы[ИмяКлючевогоРеквизита]) Тогда
|
||
СуществующиеЭлементы.Вставить(СтрокаТаблицы[ИмяКлючевогоРеквизита], НоваяСсылка);
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
Если Не ОбновитьМультиязычныеСтроки Тогда
|
||
|
||
Если ПоддерживаетсяИерархия И ЗначениеЗаполнено(СтрокаТаблицы.Родитель) Тогда
|
||
|
||
Если ИмяКлючевогоРеквизита = "Ссылка" Тогда
|
||
Если ТипЗнч(СтрокаТаблицы.Родитель) = Тип("Строка") Тогда
|
||
ЗаполняемыйЭлемент.Родитель = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаТаблицы.Родитель));
|
||
ИначеЕсли ТипЗнч(СтрокаТаблицы.Родитель) = Тип("УникальныйИдентификатор") Тогда
|
||
ЗаполняемыйЭлемент.Родитель = МенеджерОбъекта.ПолучитьСсылку(СтрокаТаблицы.Родитель);
|
||
Иначе
|
||
ЗаполняемыйЭлемент.Родитель = СтрокаТаблицы.Родитель;
|
||
КонецЕсли;
|
||
ИначеЕсли ТипЗнч(СтрокаТаблицы.Родитель) = Тип("Строка") Тогда
|
||
ЗаполняемыйЭлемент.Родитель = СуществующиеЭлементы[СтрокаТаблицы.Родитель];
|
||
Иначе
|
||
ЗаполняемыйЭлемент.Родитель = СтрокаТаблицы.Родитель;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
ПоляИсключения =?(ПоддерживаетсяИерархия И ЗаполняемыйЭлемент.ЭтоГруппа,
|
||
РеквизитыИсключенияСЭлементами, РеквизитыИсключения);
|
||
|
||
ДанныеЗаполнения = ОпределитьДанныеЗаполнения(ПредопределенныеДанные, СтрокаТаблицы, ПоляИсключения);
|
||
|
||
ЗаполнитьЗначенияСвойств(ЗаполняемыйЭлемент, ДанныеЗаполнения);
|
||
|
||
Если Не (ПоддерживаетсяИерархия И ЗаполняемыйЭлемент.ЭтоГруппа) Тогда
|
||
Для Каждого ИмяТабличнойЧасти Из ТабличныеЧасти Цикл
|
||
Если СтрокаТаблицы[ИмяТабличнойЧасти].Количество() > 0 Тогда
|
||
ЗаполняемыйЭлемент[ИмяТабличнойЧасти].Загрузить(СтрокаТаблицы[ИмяТабличнойЧасти]);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыЗаполнения.ЛокализуемыеРеквизитыОбъекта.Количество() > 0 И ПараметрыЗаполнения.ЛокализуемыеРеквизитыОбъекта["Наименование"] <> Неопределено Тогда
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
МодульМультиязычностьСервер.НачальноеЗаполнениеПредопределенныхДанныхЛокализуемыеРеквизиты(
|
||
ЗаполняемыйЭлемент, ПоддерживаетсяИерархия, СтрокаТаблицы, ПараметрыЗаполнения);
|
||
ИначеЕсли ПараметрыЗаполнения.ОбъектСодержитТЧПредставления Тогда
|
||
НачальноеЗаполнениеТЧПредставления(ЗаполняемыйЭлемент, СтрокаТаблицы, ПараметрыЗаполнения);
|
||
КонецЕсли;
|
||
ИначеЕсли ОбновитьМультиязычныеСтроки
|
||
И ПредопределенныеДанные.Колонки.Найти("Наименование") <> Неопределено
|
||
И ЗначениеЗаполнено(СтрокаТаблицы["Наименование"]) Тогда
|
||
ЗаполняемыйЭлемент["Наименование"] = СтрокаТаблицы["Наименование"];
|
||
КонецЕсли;
|
||
|
||
Если Не ОбновитьМультиязычныеСтроки И НастройкиЗаполнения.ПереопределяемыеНастройки.ПриНачальномЗаполненииЭлемента Тогда
|
||
|
||
МенеджерОбъекта.ПриНачальномЗаполненииЭлемента(ЗаполняемыйЭлемент, СтрокаТаблицы, НастройкиЗаполнения.ПереопределяемыеНастройки.ДополнительныеПараметры);
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПриНачальномЗаполненииЭлемента(МетаданныеОбъекта.ПолноеИмя(),
|
||
ЗаполняемыйЭлемент, СтрокаТаблицы, НастройкиЗаполнения.ПереопределяемыеНастройки.ДополнительныеПараметры);
|
||
|
||
КонецЕсли;
|
||
|
||
ОбновлениеИнформационнойБазы.ЗаписатьОбъект(ЗаполняемыйЭлемент);
|
||
|
||
СтрокаТаблицы.Ссылка = ЗаполняемыйЭлемент.Ссылка;
|
||
|
||
КонецЦикла;
|
||
|
||
ЗафиксироватьТранзакцию();
|
||
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
КонецЦикла;
|
||
|
||
Если ОбновитьМультиязычныеСтроки Тогда
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
|
||
МодульУправлениеДоступомСлужебный = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступомСлужебный");
|
||
МодульУправлениеДоступомСлужебный.ПриИзмененииЯзыкаИнформационнойБазы(ДополнительныеПараметры);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура НачальноеЗаполнениеТЧПредставления(ЗаполняемыйЭлемент, СтрокаТаблицы, ПараметрыЗаполнения) Экспорт
|
||
|
||
Языки = СтандартныеПодсистемыСервер.ЯзыкиКонфигурации();
|
||
ЛокализуемыеРеквизитыОбъекта = ПараметрыЗаполнения.ЛокализуемыеРеквизитыОбъекта;
|
||
|
||
Для каждого КодЯзыка Из Языки Цикл
|
||
Если СтрСравнить(КодЯзыка, ОбщегоНазначения.КодОсновногоЯзыка()) = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
ПредставленияОбъекта = ЗаполняемыйЭлемент.Представления; // ТаблицаЗначений
|
||
НовоеПредставление = ПредставленияОбъекта.Добавить();
|
||
НовоеПредставление.КодЯзыка = КодЯзыка;
|
||
Для каждого ИмяЛокализуемогоРеквизита Из ЛокализуемыеРеквизитыОбъекта Цикл
|
||
Значение = СтрокаТаблицы[ИмяЛокализуемогоРеквизита.Ключ + "_" + КодЯзыка];
|
||
НовоеПредставление[ИмяЛокализуемогоРеквизита.Ключ] = ?(ЗначениеЗаполнено(Значение), Значение, СтрокаТаблицы[ИмяЛокализуемогоРеквизита.Ключ]);
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция НаборПараметровДляЗаполненияОбъекта(МетаданныеОбъекта) Экспорт
|
||
|
||
Результат = Новый Структура;
|
||
|
||
ОбъектыСНачальнымЗаполнением = ОбъектыСНачальнымЗаполнением();
|
||
ЕстьПредопределенныеДанные = ОбъектыСНачальнымЗаполнением.Найти(МетаданныеОбъекта) <> Неопределено;
|
||
|
||
ЛокализуемыеРеквизитыОбъекта = Новый Соответствие;
|
||
МультиязычныеСтрокиВРеквизитах = Ложь;
|
||
ОбъектСодержитТЧПредставления = Ложь;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
ЛокализуемыеРеквизитыОбъекта = МодульМультиязычностьСервер.МультиязычныеРеквизитыОбъекта(МетаданныеОбъекта);
|
||
МультиязычныеСтрокиВРеквизитах = МодульМультиязычностьСервер.МультиязычныеСтрокиВРеквизитах(МетаданныеОбъекта);
|
||
ОбъектСодержитТЧПредставления = МодульМультиязычностьСервер.ОбъектСодержитТЧПредставления(МетаданныеОбъекта.ПолноеИмя());
|
||
КонецЕсли;
|
||
|
||
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(МетаданныеОбъекта.ПолноеИмя());
|
||
|
||
Если ЕстьПредопределенныеДанные Тогда
|
||
ПредопределенныеДанные = ПредопределенныеДанныеОбъекта(МетаданныеОбъекта, МенеджерОбъекта, ЛокализуемыеРеквизитыОбъекта);
|
||
НастройкиПредопределенныхЭлементов = НастройкиПредопределенныхЭлементов(МенеджерОбъекта, ПредопределенныеДанные);
|
||
Иначе
|
||
ПредопределенныеДанные = Новый ТаблицаЗначений();
|
||
НастройкиПредопределенныхЭлементов = Новый Структура;
|
||
КонецЕсли;
|
||
|
||
ТабличныеЧасти = Новый Массив;
|
||
ОбъектМетаданныхТабличныеЧасти = МетаданныеОбъекта.ТабличныеЧасти; // КоллекцияОбъектовМетаданных из ОбъектМетаданныхТабличнаяЧасть
|
||
Для Каждого ТабличнаяЧасть Из ОбъектМетаданныхТабличныеЧасти Цикл
|
||
Если ПредопределенныеДанные.Колонки.Найти(ТабличнаяЧасть.Имя) <> Неопределено Тогда
|
||
ТабличныеЧасти.Добавить(ТабличнаяЧасть.Имя);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
РеквизитыИсключения = ?(СтрНачинаетсяС(МетаданныеОбъекта.ПолноеИмя(), "ПланВидовХарактеристик"), "ТипЗначения", "");
|
||
ПоддерживаетсяИерархия = ПредопределенныеДанные.Колонки.Найти("ЭтоГруппа") <> Неопределено;
|
||
|
||
ТЧПредставленияИспользуетсяДляГрупп = Ложь;
|
||
Если ОбъектСодержитТЧПредставления И ПоддерживаетсяИерархия Тогда
|
||
|
||
Если МетаданныеОбъекта.ТабличныеЧасти.Представления.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппыИЭлемента
|
||
Или МетаданныеОбъекта.ТабличныеЧасти.Представления.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппы Тогда
|
||
ТЧПредставленияИспользуетсяДляГрупп = Истина;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
РеквизитыСЭлементами = Новый Массив;
|
||
Если ПоддерживаетсяИерархия Тогда
|
||
ДляЭлемента = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляЭлемента;
|
||
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
|
||
Если Реквизит.Использование = ДляЭлемента Тогда
|
||
РеквизитыСЭлементами.Добавить(Реквизит.Имя);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Результат.Вставить("НастройкиПредопределенныхЭлементов", НастройкиПредопределенныхЭлементов);
|
||
Результат.Вставить("ПредопределенныеДанные", ПредопределенныеДанные);
|
||
Результат.Вставить("РеквизитыИсключения", РеквизитыИсключения);
|
||
Результат.Вставить("ПоддерживаетсяИерархия", ПоддерживаетсяИерархия);
|
||
Результат.Вставить("ТабличныеЧасти", ТабличныеЧасти);
|
||
Результат.Вставить("ЛокализуемыеРеквизитыОбъекта", ЛокализуемыеРеквизитыОбъекта);
|
||
Результат.Вставить("МультиязычныеСтрокиВРеквизитах", МультиязычныеСтрокиВРеквизитах);
|
||
Результат.Вставить("ОбъектСодержитТЧПредставления", ОбъектСодержитТЧПредставления);
|
||
Результат.Вставить("ТЧПредставленияИспользуетсяДляГрупп", ТЧПредставленияИспользуетсяДляГрупп);
|
||
Результат.Вставить("МенеджерОбъекта", МенеджерОбъекта);
|
||
Результат.Вставить("РеквизитыСЭлементами", РеквизитыСЭлементами);
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
#КонецОбласти
|
||
|
||
#Область СлужебныеПроцедурыИФункции
|
||
|
||
Функция ОпределитьДанныеЗаполнения(Знач ПредопределенныеДанные, Знач СтрокаТаблицы, Знач ПоляИсключения)
|
||
|
||
ДанныеЗаполнения = Новый Структура;
|
||
Для Каждого Колонка Из ПредопределенныеДанные.Колонки Цикл
|
||
|
||
ИмяПоля = Колонка.Имя;
|
||
Если ПоляИсключения[ИмяПоля] = Истина Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Значение = СтрокаТаблицы[ИмяПоля];
|
||
Если Колонка.ТипЗначения.Типы().Количество() > 1 Тогда
|
||
Заполнено = Значение <> Неопределено;
|
||
ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
|
||
Заполнено = Значение;
|
||
Иначе
|
||
Заполнено = ЗначениеЗаполнено(Значение);
|
||
КонецЕсли;
|
||
|
||
Если Заполнено Тогда
|
||
ДанныеЗаполнения.Вставить(ИмяПоля, Значение);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат ДанныеЗаполнения;
|
||
|
||
КонецФункции
|
||
|
||
Функция ДействияПередОбновлениемИнформационнойБазы(ПараметрыОбновления)
|
||
|
||
Если Не ПараметрыОбновления.ПриЗапускеКлиентскогоПриложения Тогда
|
||
Если Не ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбновлениеКонфигурации") Тогда
|
||
МодульОбновлениеКонфигурации = ОбщегоНазначения.ОбщийМодуль("ОбновлениеКонфигурации");
|
||
МодульОбновлениеКонфигурации.ПроверитьНаличиеУстаревшихИсправлений();
|
||
КонецЕсли;
|
||
|
||
Попытка
|
||
РегистрыСведений.ПараметрыРаботыПрограммы.ЗагрузитьОбновитьПараметрыРаботыПрограммы();
|
||
Исключение
|
||
ЗаписатьОшибку(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("Возврат", "");
|
||
|
||
// Определяем факт смены имени конфигурации.
|
||
|
||
РежимОбновленияДанных = РежимОбновленияДанных();
|
||
ВерсияМетаданных = Метаданные.Версия;
|
||
Если ПустаяСтрока(ВерсияМетаданных) Тогда
|
||
ВерсияМетаданных = "0.0.0.0";
|
||
КонецЕсли;
|
||
ВерсияДанных = ВерсияИБ(Метаданные.Имя);
|
||
|
||
// Перед обновлением информационной базы.
|
||
//
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПередОбновлениемИнформационнойБазы();
|
||
|
||
// Установка привилегированного режима для возможности обновления ИБ в модели сервиса,
|
||
// в случае когда администратор области данных выполняет вход в область до завершения обновления области.
|
||
Если ОбщегоНазначения.РазделениеВключено() И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
// Загрузка и выгрузка сообщения обмена после перезапуска в связи с получением изменений конфигурации.
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.ПередОбновлениемИнформационнойБазы(ПараметрыОбновления.ПриЗапускеКлиентскогоПриложения, ПараметрыОбновления.Перезапустить);
|
||
КонецЕсли;
|
||
|
||
Если НЕ ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы() Тогда
|
||
Результат.Возврат = "НеТребуется";
|
||
Возврат Результат;
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыОбновления.ВФоне Тогда
|
||
ДлительныеОперации.СообщитьПрогресс(1);
|
||
КонецЕсли;
|
||
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
Для каждого ИмяПодсистемы Из ОписанияПодсистем.Порядок Цикл
|
||
ОписаниеПодсистемы = ОписанияПодсистем.ПоИменам.Получить(ИмяПодсистемы);
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеПодсистемы.ОсновнойСерверныйМодуль) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Модуль = ОбщегоНазначения.ОбщийМодуль(ОписаниеПодсистемы.ОсновнойСерверныйМодуль);
|
||
Модуль.ПередОбновлениемИнформационнойБазы();
|
||
КонецЦикла;
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПередОбновлениемИнформационнойБазы();
|
||
|
||
// Проверка наличия прав для обновления информационной базы.
|
||
Если НЕ ЕстьПраваНаОбновлениеИнформационнойБазы() Тогда
|
||
Сообщение = НСтр("ru = 'Недостаточно прав для обновления версии программы.'");
|
||
ЗаписатьОшибку(Сообщение);
|
||
ВызватьИсключение Сообщение;
|
||
КонецЕсли;
|
||
|
||
Если РежимОбновленияДанных = "ПереходСДругойПрограммы" Тогда
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Изменилось имя конфигурации на ""%1"".
|
||
|Будет выполнен переход с другой программы.'"),
|
||
Метаданные.Имя);
|
||
ИначеЕсли РежимОбновленияДанных = "ОбновлениеВерсии" Тогда
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Изменился номер версии конфигурации: с ""%1"" на ""%2"".
|
||
|Будет выполнено обновление информационной базы.'"),
|
||
ВерсияДанных, ВерсияМетаданных);
|
||
Иначе
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Выполняется начальное заполнение данных до версии ""%1"".'"),
|
||
ВерсияМетаданных);
|
||
КонецЕсли;
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
// Установка блокировки информационной базы.
|
||
БлокировкаУстановленаРанее = ПараметрыОбновления.УстановленнаяБлокировкаИБ <> Неопределено
|
||
И ПараметрыОбновления.УстановленнаяБлокировкаИБ.Установлена;
|
||
Если БлокировкаУстановленаРанее Тогда
|
||
ИтерацииОбновления = ИтерацииОбновления();
|
||
БлокировкаИБ = ПараметрыОбновления.УстановленнаяБлокировкаИБ;
|
||
Иначе
|
||
БлокировкаИБ = Неопределено;
|
||
ИтерацииОбновления = ЗаблокироватьИБ(БлокировкаИБ, ПараметрыОбновления.ИсключениеПриНевозможностиБлокировкиИБ);
|
||
Если БлокировкаИБ.Ошибка <> Неопределено Тогда
|
||
Результат.Возврат = БлокировкаИБ.Ошибка;
|
||
Возврат Результат;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Результат.Вставить("РежимОбновленияДанных", РежимОбновленияДанных);
|
||
Результат.Вставить("ИтерацииОбновления", ИтерацииОбновления);
|
||
Результат.Вставить("БлокировкаИБ", БлокировкаИБ);
|
||
Результат.Вставить("БлокировкаУстановленаРанее", БлокировкаУстановленаРанее);
|
||
Результат.Вставить("ВерсияДанных", ВерсияДанных);
|
||
Результат.Вставить("ВерсияМетаданных", ВерсияМетаданных);
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ВыполнитьДействияПриОбновленииИнформационнойБазы(ПараметрыОбновления, ДополнительныеПараметры)
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
// Установка привилегированного режима для возможности обновления ИБ в модели сервиса,
|
||
// в случае когда администратор области данных выполняет вход в область до завершения обновления области.
|
||
Если ОбщегоНазначения.РазделениеВключено() И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
РежимОбновленияДанных = ДополнительныеПараметры.РежимОбновленияДанных;
|
||
ИтерацииОбновления = ДополнительныеПараметры.ИтерацииОбновления;
|
||
БлокировкаИБ = ДополнительныеПараметры.БлокировкаИБ;
|
||
БлокировкаУстановленаРанее = ДополнительныеПараметры.БлокировкаУстановленаРанее;
|
||
РежимВыполненияОтложенногоОбновления = ДополнительныеПараметры.РежимВыполненияОтложенногоОбновления;
|
||
ВыполнитьОтложенноеОбновлениеСейчас = ДополнительныеПараметры.ВыполнитьОтложенноеОбновлениеСейчас;
|
||
|
||
ОперативноеОбновление = БлокировкаИБ.ОперативноеОбновление;
|
||
|
||
Попытка
|
||
|
||
Если РежимОбновленияДанных = "ПереходСДругойПрограммы" Тогда
|
||
ПерейтиСДругойПрограммы(ИтерацииОбновления);
|
||
ИтерацииОбновления = ИтерацииОбновления();
|
||
|
||
РежимОбновленияДанных = РежимОбновленияДанных();
|
||
ОперативноеОбновление = Ложь;
|
||
КонецЕсли;
|
||
|
||
Исключение
|
||
Если Не БлокировкаУстановленаРанее Тогда
|
||
РазблокироватьИБ(БлокировкаИБ);
|
||
КонецЕсли;
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПередФормированиеСпискаОтложенныхОбработчиков(ИтерацииОбновления);
|
||
Обработки.ОписаниеОбработчиковОбновления.ЗаполнитьНомерОчереди(ИтерацииОбновления);
|
||
ОбновитьСписокВыполняемыхОбработчиковОбновления(ИтерацииОбновления);
|
||
СброситьПрогрессВыполненияОбработчиков();
|
||
ОчиститьЗарегистрированныеПроблемыСДанными();
|
||
|
||
Если ПараметрыОбновления.ВФоне Тогда
|
||
ДлительныеОперации.СообщитьПрогресс(10);
|
||
КонецЕсли;
|
||
|
||
Параметры = Новый Структура;
|
||
Параметры.Вставить("ХодВыполненияОбработчиков", КоличествоОбработчиковНаТекущуюВерсию(ИтерацииОбновления, РежимВыполненияОтложенногоОбновления));
|
||
Параметры.Вставить("ОперативноеОбновление", ОперативноеОбновление);
|
||
Параметры.Вставить("ВФоне", ПараметрыОбновления.ВФоне);
|
||
Параметры.Вставить("ПриЗапускеКлиентскогоПриложения", ПараметрыОбновления.ПриЗапускеКлиентскогоПриложения);
|
||
Параметры.Вставить("РежимВыполненияОтложенногоОбновления", РежимВыполненияОтложенногоОбновления);
|
||
|
||
Сообщение = НСтр("ru = 'Для обновления программы на новую версию будут выполнены обработчики: %1'");
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение, Параметры.ХодВыполненияОбработчиков.ВсегоОбработчиков);
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
Попытка
|
||
|
||
// Выполняем все обработчики обновления для подсистем конфигурации.
|
||
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
|
||
ИтерацияОбновления.ВыполненныеОбработчики = ВыполнитьИтерациюОбновления(ИтерацияОбновления, Параметры);
|
||
КонецЦикла;
|
||
|
||
// Очистка списка новых подсистем.
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
СведенияОбОбновлении.НовыеПодсистемы = Новый Массив;
|
||
СведенияОбОбновлении.ВсеНовыеПодсистемы = Новый Массив;
|
||
ЗаполнитьДанныеДляПараллельногоОтложенногоОбновления(Параметры);
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
// Для файловой базы отложенные обработчики выполняются в основном цикле обновления.
|
||
Если ВыполнитьОтложенноеОбновлениеСейчас Тогда
|
||
ВыполнитьОтложенноеОбновлениеСейчас(Параметры);
|
||
КонецЕсли;
|
||
|
||
Исключение
|
||
Если Не БлокировкаУстановленаРанее Тогда
|
||
РазблокироватьИБ(БлокировкаИБ);
|
||
КонецЕсли;
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ВыполнитьДействияПослеОбновленияИнформационнойБазы(ПараметрыОбновления, ДополнительныеПараметры)
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
// Установка привилегированного режима для возможности обновления ИБ в модели сервиса,
|
||
// в случае когда администратор области данных выполняет вход в область до завершения обновления области.
|
||
Если ОбщегоНазначения.РазделениеВключено() И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
РежимОбновленияДанных = ДополнительныеПараметры.РежимОбновленияДанных;
|
||
ИтерацииОбновления = ДополнительныеПараметры.ИтерацииОбновления;
|
||
БлокировкаИБ = ДополнительныеПараметры.БлокировкаИБ;
|
||
ОперативноеОбновление = ДополнительныеПараметры.БлокировкаИБ.ОперативноеОбновление;
|
||
ВерсияДанных = ДополнительныеПараметры.ВерсияДанных;
|
||
ВерсияМетаданных = ДополнительныеПараметры.ВерсияМетаданных;
|
||
БлокировкаУстановленаРанее = ДополнительныеПараметры.БлокировкаУстановленаРанее;
|
||
РежимВыполненияОтложенногоОбновления = ДополнительныеПараметры.РежимВыполненияОтложенногоОбновления;
|
||
ВыполнитьОтложенноеОбновлениеСейчас = ДополнительныеПараметры.ВыполнитьОтложенноеОбновлениеСейчас;
|
||
|
||
// Отключение монопольного режима.
|
||
Если Не БлокировкаУстановленаРанее Тогда
|
||
РазблокироватьИБ(БлокировкаИБ);
|
||
КонецЕсли;
|
||
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Обновление информационной базы на версию ""%1"" выполнено успешно.'"), ВерсияМетаданных);
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
ВыводитьОписаниеОбновлений = (РежимОбновленияДанных <> "НачальноеЗаполнение");
|
||
|
||
ОбновитьПовторноИспользуемыеЗначения();
|
||
|
||
// После обновления информационной базы.
|
||
//
|
||
ВыполнитьОбработчикиПослеОбновленияИнформационнойБазы(
|
||
ИтерацииОбновления,
|
||
Константы.ДетализироватьОбновлениеИБВЖурналеРегистрации.Получить(),
|
||
ВыводитьОписаниеОбновлений,
|
||
ОперативноеОбновление);
|
||
|
||
ОбновлениеИнформационнойБазыПереопределяемый.ПослеОбновленияИнформационнойБазы(
|
||
ВерсияДанных,
|
||
ВерсияМетаданных,
|
||
ИтерацииОбновления,
|
||
ВыводитьОписаниеОбновлений,
|
||
Не ОперативноеОбновление);
|
||
|
||
// Выгрузка сообщения обмена после перезапуска в связи с получением изменений конфигурации.
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.ПослеОбновленияИнформационнойБазы();
|
||
КонецЕсли;
|
||
|
||
// Для клиент-серверной базы запланировать выполнение отложенных обработчиков обновления.
|
||
Если РежимВыполненияОтложенногоОбновления <> Неопределено
|
||
И РежимВыполненияОтложенногоОбновления = "Отложенно" Тогда
|
||
ЗапланироватьОтложенноеОбновление();
|
||
КонецЕсли;
|
||
|
||
ОпределитьВыводОписанияОбновлений(ВыводитьОписаниеОбновлений);
|
||
|
||
// Сброс неуспешного статуса обновления конфигурации при завершении обновления вручную (без скрипта).
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбновлениеКонфигурации") Тогда
|
||
МодульОбновлениеКонфигурации = ОбщегоНазначения.ОбщийМодуль("ОбновлениеКонфигурации");
|
||
МодульОбновлениеКонфигурации.ПослеОбновленияИнформационнойБазы();
|
||
КонецЕсли;
|
||
|
||
ОбновитьПовторноИспользуемыеЗначения();
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
ПараметрЗапускаКлиента = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ПараметрЗапуска");
|
||
Если СтрНайти(НРег(ПараметрЗапускаКлиента), НРег("ЗапуститьОбновлениеИнформационнойБазы")) > 0 Тогда
|
||
СтандартныеПодсистемыСервер.ЗарегистрироватьИзменениеПриоритетныхДанныхДляПодчиненныхУзловРИБ();
|
||
КонецЕсли;
|
||
УстановитьПривилегированныйРежим(Ложь);
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
|
||
МодульУправлениеДоступомСлужебный = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступомСлужебный");
|
||
МодульУправлениеДоступомСлужебный.ОбновитьДоступПослеОбновленияИнформационнойБазы(
|
||
ВыполнитьОтложенноеОбновлениеСейчас);
|
||
КонецЕсли;
|
||
|
||
Если Не ПараметрыОбновления.ПриЗапускеКлиентскогоПриложения Тогда
|
||
УстановитьЗапускОбновленияИнформационнойБазы(Ложь);
|
||
ПараметрыСеанса.ВыполняетсяОбновлениеИБ = Ложь;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Возвращает признак разрешения использования многопоточного обновления.
|
||
// Многопоточное обновление можно включить в ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек().
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - если Истина, многопоточное обновление разрешено. По умолчанию - Ложь (для обратной совместимости).
|
||
//
|
||
Функция РазрешеноМногопоточноеОбновление() Экспорт
|
||
|
||
Параметры = НастройкиПодсистемы();
|
||
Возврат Параметры.МногопоточноеОбновление;
|
||
|
||
КонецФункции
|
||
|
||
// Параметры:
|
||
// ИмяПараметра - Строка
|
||
// УстановленныеПараметры - Массив из Строка
|
||
//
|
||
Процедура УстановкаПараметровСеанса(Знач ИмяПараметра, УстановленныеПараметры) Экспорт
|
||
|
||
Если ИмяПараметра = "ВыполняетсяОбновлениеИБ" Тогда
|
||
ПараметрыСеанса.ВыполняетсяОбновлениеИБ = ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы();
|
||
УстановленныеПараметры.Добавить("ВыполняетсяОбновлениеИБ");
|
||
ИначеЕсли ИмяПараметра = "ПараметрыОбработчикаОбновления" Тогда
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(НовыеПараметрыОбработчикаОбновления());
|
||
УстановленныеПараметры.Добавить("ПараметрыОбработчикаОбновления");
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Возвращает числовой вес версии для сравнения версий между собой.
|
||
//
|
||
// Параметры:
|
||
// Версия - Строка - версия в строковом формате.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - вес версии
|
||
//
|
||
Функция ВесВерсии(Знач Версия) Экспорт
|
||
|
||
Если Версия = "" Тогда
|
||
Возврат 0;
|
||
КонецЕсли;
|
||
|
||
Если СтрНачинаетсяС(Версия, "ОтладкаОбработчика") Тогда
|
||
Возврат 99000000000;
|
||
КонецЕсли;
|
||
|
||
Возврат ВесВерсииИзМассиваСтрок(СтрРазделить(Версия, "."));
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
// Параметры:
|
||
// ИмяКонфигурацииИлиБиблиотеки - Строка
|
||
// Версия - Строка
|
||
// Обработчики - см. ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления
|
||
// ЭтоОсновнаяКонфигурация - Булево
|
||
// - Неопределено
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ПредыдущаяВерсия - Строка
|
||
// * ОсновнойСерверныйМодуль - Строка
|
||
// * ИмяОсновногоСерверногоМодуля - Строка
|
||
// * ВыполненныеОбработчики - Неопределено
|
||
// * Обработчики - ТаблицаЗначений:
|
||
// ** НачальноеЗаполнение - Булево
|
||
// ** Версия - Строка
|
||
// ** Процедура - Строка
|
||
// ** РежимВыполнения - Строка
|
||
// ** ОбщиеДанные - Булево
|
||
// ** УправлениеОбработчиками - Булево
|
||
// ** Комментарий - Строка
|
||
// ** Идентификатор - УникальныйИдентификатор
|
||
// ** БлокируемыеОбъекты - Строка
|
||
// ** ПроцедураПроверки - Строка
|
||
// ** ПроцедураЗаполненияДанныхОбновления - Строка
|
||
// ** ЗапускатьТолькоВГлавномУзле - Булево
|
||
// ** ЗапускатьИВПодчиненномУзлеРИБСФильтрами - Булево
|
||
// ** ЧитаемыеОбъекты - Строка
|
||
// ** ИзменяемыеОбъекты - Строка
|
||
// ** ПриоритетыВыполнения - ТаблицаЗначений
|
||
// ** ВыполнятьВГруппеОбязательных - Булево
|
||
// ** Приоритет - Число
|
||
// ** МонопольныйРежим - Неопределено
|
||
// - Булево
|
||
// * ЭтоОсновнаяКонфигурация - Булево
|
||
// - Неопределено
|
||
//
|
||
Функция ИтерацияОбновления(ИмяКонфигурацииИлиБиблиотеки, Версия, Обработчики, ЭтоОсновнаяКонфигурация = Неопределено) Экспорт
|
||
|
||
ИтерацияОбновления = Новый Структура;
|
||
ИтерацияОбновления.Вставить("Подсистема", ИмяКонфигурацииИлиБиблиотеки);
|
||
ИтерацияОбновления.Вставить("Версия", Версия);
|
||
ИтерацияОбновления.Вставить("ЭтоОсновнаяКонфигурация",
|
||
?(ЭтоОсновнаяКонфигурация <> Неопределено, ЭтоОсновнаяКонфигурация, ИмяКонфигурацииИлиБиблиотеки = Метаданные.Имя));
|
||
ИтерацияОбновления.Вставить("Обработчики", Обработчики);
|
||
ИтерацияОбновления.Вставить("ВыполненныеОбработчики", Неопределено);
|
||
ИтерацияОбновления.Вставить("ИмяОсновногоСерверногоМодуля", "");
|
||
ИтерацияОбновления.Вставить("ОсновнойСерверныйМодуль", "");
|
||
ИтерацияОбновления.Вставить("ПредыдущаяВерсия", "");
|
||
Возврат ИтерацияОбновления;
|
||
|
||
КонецФункции
|
||
|
||
// Проверить права текущего пользователя на выполнение обновления информационной базы.
|
||
Функция ЕстьПраваНаОбновлениеИнформационнойБазы(УчитыватьПривилегированныйРежим = Истина, РазделенныеДанные = Неопределено) Экспорт
|
||
|
||
ПроверятьПраваАдминистрированияСистемы = Истина;
|
||
|
||
Если РазделенныеДанные = Неопределено Тогда
|
||
РазделенныеДанные = НЕ ОбщегоНазначения.РазделениеВключено()
|
||
ИЛИ ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И РазделенныеДанные Тогда
|
||
|
||
Если НЕ ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
ПроверятьПраваАдминистрированияСистемы = Ложь;
|
||
КонецЕсли;
|
||
|
||
Возврат Пользователи.ЭтоПолноправныйПользователь(
|
||
, ПроверятьПраваАдминистрированияСистемы, УчитыватьПривилегированныйРежим);
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция ОбновитьИнформационнуюБазуВФоне(УникальныйИдентификаторФормы, БлокировкаИБ) Экспорт
|
||
|
||
// Запуск фонового задания
|
||
ПараметрыОбновленияИБ = Новый Структура;
|
||
ПараметрыОбновленияИБ.Вставить("ИсключениеПриНевозможностиБлокировкиИБ", Ложь);
|
||
ПараметрыОбновленияИБ.Вставить("БлокировкаИБ", БлокировкаИБ);
|
||
ПараметрыОбновленияИБ.Вставить("ПараметрыКлиентаНаСервере", ПараметрыСеанса.ПараметрыКлиентаНаСервере);
|
||
|
||
// Установка монопольного режима до запуска фонового выполнения обновления.
|
||
Попытка
|
||
ЗаблокироватьИБ(ПараметрыОбновленияИБ.БлокировкаИБ, Ложь);
|
||
Исключение
|
||
ИнформацияОбОшибке = ИнформацияОбОшибке();
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("Статус", "Ошибка");
|
||
Результат.Вставить("БлокировкаИБ", ПараметрыОбновленияИБ.БлокировкаИБ);
|
||
Результат.Вставить("КраткоеПредставлениеОшибки", КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
|
||
Результат.Вставить("ПодробноеПредставлениеОшибки", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
|
||
|
||
Возврат Результат;
|
||
КонецПопытки;
|
||
|
||
ПараметрыОбновленияИБ.Вставить("ВФоне", Не ПараметрыОбновленияИБ.БлокировкаИБ.РежимОтладки);
|
||
|
||
Если Не ПараметрыОбновленияИБ.ВФоне Тогда
|
||
ПараметрыОбновленияИБ.Удалить("ПараметрыКлиентаНаСервере");
|
||
КонецЕсли;
|
||
|
||
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификаторФормы);
|
||
ПараметрыВыполнения.ОжидатьЗавершение = 0;
|
||
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Фоновое обновление информационной базы'");
|
||
|
||
Результат = ДлительныеОперации.ВыполнитьВФоне("ОбновлениеИнформационнойБазыСлужебный.ВыполнитьОбновлениеИнформационнойБазыВФоне",
|
||
ПараметрыОбновленияИБ, ПараметрыВыполнения);
|
||
|
||
Результат.Вставить("БлокировкаИБ", ПараметрыОбновленияИБ.БлокировкаИБ);
|
||
|
||
// Если обновление ИБ уже выполнилось - разблокируем ИБ.
|
||
Если Результат.Статус <> "Выполняется" Тогда
|
||
РазблокироватьИБ(ПараметрыОбновленияИБ.БлокировкаИБ);
|
||
КонецЕсли;
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// Запускает обновление информационной базы в длительной операции.
|
||
Процедура ВыполнитьОбновлениеИнформационнойБазыВФоне(ПараметрыОбновленияИБ, АдресХранилища) Экспорт
|
||
|
||
Если ПараметрыОбновленияИБ.ВФоне Тогда
|
||
ПараметрыСеанса.ПараметрыКлиентаНаСервере = ПараметрыОбновленияИБ.ПараметрыКлиентаНаСервере;
|
||
КонецЕсли;
|
||
|
||
ИнформацияОбОшибке = Неопределено;
|
||
Попытка
|
||
ПараметрыОбновления = ПараметрыОбновления();
|
||
ПараметрыОбновления.ИсключениеПриНевозможностиБлокировкиИБ = ПараметрыОбновленияИБ.ИсключениеПриНевозможностиБлокировкиИБ;
|
||
ПараметрыОбновления.ПриЗапускеКлиентскогоПриложения = Истина;
|
||
ПараметрыОбновления.Перезапустить = Ложь;
|
||
ПараметрыОбновления.УстановленнаяБлокировкаИБ = ПараметрыОбновленияИБ.БлокировкаИБ;
|
||
ПараметрыОбновления.ВФоне = ПараметрыОбновленияИБ.ВФоне;
|
||
|
||
Результат = ВыполнитьОбновлениеИнформационнойБазы(ПараметрыОбновления);
|
||
Исключение
|
||
ИнформацияОбОшибке = ИнформацияОбОшибке();
|
||
// Переход в режим открытия формы повторной синхронизации данных перед запуском
|
||
// с двумя вариантами "Синхронизировать и продолжить" и "Продолжить".
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными")
|
||
И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.ВключитьПовторениеЗагрузкиСообщенияОбменаДаннымиПередЗапуском();
|
||
КонецЕсли;
|
||
КонецПопытки;
|
||
|
||
Если ИнформацияОбОшибке <> Неопределено Тогда
|
||
РезультатОбновления = Новый Структура;
|
||
РезультатОбновления.Вставить("КраткоеПредставлениеОшибки", КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
|
||
РезультатОбновления.Вставить("ПодробноеПредставлениеОшибки", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
|
||
ИначеЕсли Не ПараметрыОбновленияИБ.ВФоне Тогда
|
||
РезультатОбновления = Результат;
|
||
Иначе
|
||
РезультатОбновления = Новый Структура;
|
||
РезультатОбновления.Вставить("ПараметрыКлиентаНаСервере", ПараметрыСеанса.ПараметрыКлиентаНаСервере);
|
||
РезультатОбновления.Вставить("Результат", Результат);
|
||
КонецЕсли;
|
||
ПоместитьВоВременноеХранилище(РезультатОбновления, АдресХранилища);
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОбновлениеПодОграниченнымиПравами() Экспорт
|
||
Если Не ОбщегоНазначения.РазделениеВключено()
|
||
Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Результат = "";
|
||
// АПК:280 -выкл ошибки пишутся в журнал регистрации, пользователю не показываются.
|
||
Попытка
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
ОтметкаНачалаОбновления = ОтметкаНачалаОбновления();
|
||
Если ОтметкаНачалаОбновления.МожноВыполнятьОбновление Тогда
|
||
Результат = ОбновлениеИнформационнойБазы.ВыполнитьОбновлениеИнформационнойБазы();
|
||
КонецЕсли;
|
||
УстановитьПривилегированныйРежим(Ложь);
|
||
Исключение
|
||
// Обработка исключения не требуется.
|
||
КонецПопытки;
|
||
// АПК:280 -вкл.
|
||
|
||
Возврат (Результат = "Успешно" Или Результат = "НеТребуется");
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция ЗаблокироватьИБ(БлокировкаИБ, ИсключениеПриНевозможностиБлокировкиИБ)
|
||
|
||
ИтерацииОбновления = Неопределено;
|
||
Если БлокировкаИБ = Неопределено Тогда
|
||
БлокировкаИБ = БлокировкаИБ();
|
||
КонецЕсли;
|
||
|
||
БлокировкаИБ.Установлена = Истина;
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
БлокировкаИБ.РежимОтладки = Ложь;
|
||
Иначе
|
||
БлокировкаИБ.РежимОтладки = ОбщегоНазначения.РежимОтладки();
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
БлокировкаИБ.КлючЗаписи = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ЗаблокироватьВерсииОбластиДанных();
|
||
КонецЕсли;
|
||
|
||
ИтерацииОбновления = ИтерацииОбновления();
|
||
БлокировкаИБ.ОперативноеОбновление = Ложь;
|
||
|
||
Если БлокировкаИБ.РежимОтладки Тогда
|
||
Возврат ИтерацииОбновления;
|
||
КонецЕсли;
|
||
|
||
// Установка монопольного режима для обновления информационной базы.
|
||
ИнформацияОбОшибке = Неопределено;
|
||
Попытка
|
||
Если НЕ МонопольныйРежим() Тогда
|
||
УстановитьМонопольныйРежим(Истина);
|
||
КонецЕсли;
|
||
Возврат ИтерацииОбновления;
|
||
Исключение
|
||
Если ВозможноОперативноеОбновление(ИтерацииОбновления) Тогда
|
||
БлокировкаИБ.ОперативноеОбновление = Истина;
|
||
Возврат ИтерацииОбновления;
|
||
КонецЕсли;
|
||
ИнформацияОбОшибке = ИнформацияОбОшибке();
|
||
КонецПопытки;
|
||
|
||
// Обработка неудачной попытки установки монопольного режима.
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Невозможно выполнить обновление информационной базы:
|
||
|- Невозможно установить монопольный режим
|
||
|- Версия конфигурации не предусматривает обновление без установки монопольного режима
|
||
|
|
||
|Подробности ошибки:
|
||
|%1'"),
|
||
КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
|
||
|
||
ЗаписатьОшибку(Сообщение);
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.РазблокироватьВерсииОбластиДанных(БлокировкаИБ.КлючЗаписи);
|
||
КонецЕсли;
|
||
|
||
Если Не ИсключениеПриНевозможностиБлокировкиИБ
|
||
И ОбщегоНазначения.ИнформационнаяБазаФайловая()
|
||
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЗавершениеРаботыПользователей") Тогда
|
||
|
||
ПараметрЗапускаКлиента = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ПараметрЗапуска");
|
||
Если СтрНайти(ПараметрЗапускаКлиента, "РегламентныеЗаданияОтключены") = 0 Тогда
|
||
БлокировкаИБ.Ошибка = "ЗаблокироватьВыполнениеРегламентныхЗаданий";
|
||
Иначе
|
||
БлокировкаИБ.Ошибка = "ОшибкаУстановкиМонопольногоРежима";
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ВызватьИсключение Сообщение;
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Процедура РазблокироватьИБ(БлокировкаИБ) Экспорт
|
||
|
||
Если БлокировкаИБ.РежимОтладки Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если МонопольныйРежим() Тогда
|
||
Пока ТранзакцияАктивна() Цикл
|
||
ОтменитьТранзакцию();
|
||
КонецЦикла;
|
||
|
||
УстановитьМонопольныйРежим(Ложь);
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.РазблокироватьВерсииОбластиДанных(БлокировкаИБ.КлючЗаписи);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция БлокировкаИБ()
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("Установлена", Ложь);
|
||
Результат.Вставить("Ошибка", Неопределено);
|
||
Результат.Вставить("ОперативноеОбновление", Неопределено);
|
||
Результат.Вставить("КлючЗаписи", Неопределено);
|
||
Результат.Вставить("РежимОтладки", Неопределено);
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция ПараметрыОбновления() Экспорт
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("ИсключениеПриНевозможностиБлокировкиИБ", Истина);
|
||
Результат.Вставить("ПриЗапускеКлиентскогоПриложения", Ложь);
|
||
Результат.Вставить("Перезапустить", Ложь);
|
||
Результат.Вставить("УстановленнаяБлокировкаИБ", Неопределено);
|
||
Результат.Вставить("ВФоне", Ложь);
|
||
Результат.Вставить("ВыполнятьОтложенныеОбработчики", Ложь);
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция НоваяТаблицаОбработчиковПереходаСДругойПрограммы()
|
||
|
||
Обработчики = Новый ТаблицаЗначений;
|
||
Обработчики.Колонки.Добавить("ПредыдущееИмяКонфигурации", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)));
|
||
Обработчики.Колонки.Добавить("Процедура", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)));
|
||
Обработчики.Колонки.Добавить("ОбщиеДанные", Новый ОписаниеТипов("Булево"));
|
||
Возврат Обработчики;
|
||
|
||
КонецФункции
|
||
|
||
// Для внутреннего использования.
|
||
//
|
||
Функция ОбработчикиПереходаСДругойПрограммы(ПредыдущееИмяКонфигурации, ИтерацииОбновления)
|
||
|
||
ОбработчикиПерехода = НоваяТаблицаОбработчиковПереходаСДругойПрограммы();
|
||
ИмяОсновнойКонфигурации = Метаданные.Имя;
|
||
|
||
// Начальное заполнение для объектов новых подсистем.
|
||
ОбработчикиПерехода = НоваяТаблицаОбработчиковПереходаСДругойПрограммы();
|
||
ИмяОсновнойКонфигурации = Метаданные.Имя;
|
||
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
ПодсистемыКонфигурации = ОписанияПодсистем.ПоИменам;
|
||
ВсеНовыеПодсистемы = СведенияОбОбновленииИнформационнойБазы().ВсеНовыеПодсистемы;
|
||
|
||
// Добавление обработчика заполнения предопределенных данных.
|
||
ОбработчикПерехода = ОбработчикиПерехода.Добавить();
|
||
ОбработчикПерехода.ПредыдущееИмяКонфигурации = "*";
|
||
ОбработчикПерехода.ОбщиеДанные = Ложь;
|
||
ОбработчикПерехода.Процедура = ОбработчикНачальногоЗаполненияПредопределенных();
|
||
|
||
НовыеОбъектыМетаданных = Новый Массив;
|
||
Для Каждого Подсистема Из ВсеНовыеПодсистемы Цикл
|
||
ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(Подсистема);
|
||
Если ОбъектМетаданных = Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ОбъектМетаданных.ВключатьВКомандныйИнтерфейс Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Для Каждого ОбъектПодсистемы Из ОбъектМетаданных.Состав Цикл
|
||
НовыеОбъектыМетаданных.Добавить(ОбъектПодсистемы.ПолноеИмя());
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
|
||
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
|
||
|
||
ОписаниеПодсистемы = ПодсистемыКонфигурации.Получить(ИтерацияОбновления.Подсистема);
|
||
Если Не ОписаниеПодсистемы.ЗаполнятьДанныеНовыхПодсистемПриПереходеСДругойПрограммы Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Отбор = Новый Структура;
|
||
Отбор.Вставить("НачальноеЗаполнение", Истина);
|
||
|
||
ОбработчикиНачальногоЗаполнения = ИтерацияОбновления.Обработчики.НайтиСтроки(Отбор);
|
||
Для Каждого Обработчик Из ОбработчикиНачальногоЗаполнения Цикл
|
||
Если Обработчик.РежимВыполнения = "Отложенно"
|
||
Или Обработчик.НеВыполнятьПриПереходеСДругойПрограммы Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Позиция = СтрНайти(Обработчик.Процедура, ".", НаправлениеПоиска.СКонца);
|
||
ИмяМенеджера = Лев(Обработчик.Процедура, Позиция - 1);
|
||
ПолноеИмяОбъекта = ИмяОбъектаМетаданныхПоИмениМенеджера(ИмяМенеджера);
|
||
|
||
Если НовыеОбъектыМетаданных.Найти(ПолноеИмяОбъекта) <> Неопределено Тогда
|
||
ОбработчикПерехода = ОбработчикиПерехода.Добавить();
|
||
ОбработчикПерехода.ПредыдущееИмяКонфигурации = "*";
|
||
ОбработчикПерехода.ОбщиеДанные = Обработчик.ОбщиеДанные;
|
||
ОбработчикПерехода.Процедура = Обработчик.Процедура;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
|
||
// Добавление штатных обработчиков перехода.
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
Для каждого ИмяПодсистемы Из ОписанияПодсистем.Порядок Цикл
|
||
ОписаниеПодсистемы = ОписанияПодсистем.ПоИменам.Получить(ИмяПодсистемы); // см. СтандартныеПодсистемыПовтИсп.НовоеОписаниеПодсистемы
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеПодсистемы.ОсновнойСерверныйМодуль) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ОписаниеПодсистемы.Имя <> ИмяОсновнойКонфигурации Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Модуль = ОбщегоНазначения.ОбщийМодуль(ОписаниеПодсистемы.ОсновнойСерверныйМодуль);
|
||
Модуль.ПриДобавленииОбработчиковПереходаСДругойПрограммы(ОбработчикиПерехода);
|
||
КонецЦикла;
|
||
// Дополнительно добавляются обязательные обработчики перехода БСП.
|
||
ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковПереходаСДругойПрограммы(ОбработчикиПерехода);
|
||
|
||
Отбор = Новый Структура("ПредыдущееИмяКонфигурации", "*");
|
||
Если ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Отбор.Вставить("ОбщиеДанные", Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных());
|
||
КонецЕсли;
|
||
ВыбранныеОбработчики = ОбработчикиПерехода.НайтиСтроки(Отбор);
|
||
|
||
Отбор.ПредыдущееИмяКонфигурации = ПредыдущееИмяКонфигурации;
|
||
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ВыбранныеОбработчики, ОбработчикиПерехода.НайтиСтроки(Отбор), Истина);
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("Обработчики", ВыбранныеОбработчики);
|
||
Результат.Вставить("НовыеОбъекты", НовыеОбъектыМетаданных);
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ПерейтиСДругойПрограммы(ИтерацииОбновления)
|
||
|
||
ЭтоНеразделенныйСеанс = Не ОбщегоНазначения.РазделениеВключено()
|
||
Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
|
||
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = Неопределено;
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
КонецЕсли;
|
||
|
||
// Предыдущее имя конфигурации, с которой нужно выполнить переход.
|
||
Если ЭтоНеразделенныйСеанс Тогда
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ ПЕРВЫЕ 1
|
||
| ВерсииПодсистем.ИмяПодсистемы КАК ИмяПодсистемы,
|
||
| ВерсииПодсистем.Версия КАК Версия
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
|
||
|ГДЕ
|
||
| ВерсииПодсистем.ЭтоОсновнаяКонфигурация = ИСТИНА";
|
||
РезультатЗапроса = Запрос.Выполнить();
|
||
ИначеЕсли МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = Неопределено Тогда
|
||
// Отсутствует подсистема ОбновлениеВерсииИБВМоделиСервиса.
|
||
Возврат;
|
||
Иначе
|
||
РезультатЗапроса = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ОсновнаяКонфигурацияВОбластиДанных();
|
||
КонецЕсли;
|
||
// Если по каким-то причинам не отработал обработчик обновления ЗаполнитьРеквизитЭтоОсновнаяКонфигурация.
|
||
Если РезультатЗапроса.Пустой() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
РезультатЗапроса = РезультатЗапроса.Выгрузить()[0];
|
||
ПредыдущееИмяКонфигурации = РезультатЗапроса.ИмяПодсистемы;
|
||
ПредыдущаяВерсияКонфигурации = РезультатЗапроса.Версия;
|
||
|
||
// Проверка заполнения реквизита ЭтоОсновнаяКонфигурация в областях.
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ЗаполнитьПризнакЭтоОсновнаяКонфигурация(ПредыдущееИмяКонфигурации);
|
||
Иначе
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
ОписаниеПредыдущейПодсистемы = ОписанияПодсистем.ПоИменам.Получить(ПредыдущееИмяКонфигурации);
|
||
Если ОписаниеПредыдущейПодсистемы = Неопределено Тогда
|
||
// Предыдущая подсистема была удалена.
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("ИмяБиблиотеки", ПредыдущееИмяКонфигурации);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.ИмяБиблиотеки = &ИмяБиблиотеки
|
||
| И ОбработчикиОбновления.Статус <> &Статус";
|
||
Результат = Запрос.Выполнить().Выгрузить();
|
||
Для Каждого Строка Из Результат Цикл
|
||
НаборЗаписей = РегистрыСведений.ОбработчикиОбновления.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИмяОбработчика.Установить(Строка.ИмяОбработчика);
|
||
НаборЗаписей.Прочитать();
|
||
|
||
НаборЗаписей[0].ИмяБиблиотеки = Метаданные.Имя;
|
||
|
||
НаборЗаписей.Записать();
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ОбработчикиИНовыеОбъекты = ОбработчикиПереходаСДругойПрограммы(ПредыдущееИмяКонфигурации, ИтерацииОбновления);
|
||
Обработчики = ОбработчикиИНовыеОбъекты.Обработчики;
|
||
НовыеОбъекты = ОбработчикиИНовыеОбъекты.НовыеОбъекты;
|
||
|
||
ПодсистемаСуществует = ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом");
|
||
// Выполняем все обработчики перехода.
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
|
||
ТранзакцияАктивнаНаНачалоВыполнения = ТранзакцияАктивна();
|
||
ОтключитьОбновлениеКлючейДоступа(Истина, ПодсистемаСуществует);
|
||
Попытка
|
||
// Начальное заполнение предопределенных для новых объектов.
|
||
Если Обработчик.Процедура = ОбработчикНачальногоЗаполненияПредопределенных() Тогда
|
||
ПараметрыОбработчика = Новый Массив;
|
||
ПараметрыОбработчика.Добавить(Ложь);
|
||
ПараметрыОбработчика.Добавить(Новый Структура("НовыеОбъекты", НовыеОбъекты));
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(Обработчик.Процедура, ПараметрыОбработчика);
|
||
Иначе
|
||
// Выполнение обработчиков перехода.
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(Обработчик.Процедура);
|
||
КонецЕсли;
|
||
ОтключитьОбновлениеКлючейДоступа(Ложь, ПодсистемаСуществует);
|
||
Исключение
|
||
|
||
ОтключитьОбновлениеКлючейДоступа(Ложь, ПодсистемаСуществует);
|
||
ИмяОбработчика = Обработчик.Процедура;
|
||
ЗаписатьОшибку(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'При вызове обработчика перехода с другой программы
|
||
|""%1""
|
||
|произошла ошибка:
|
||
|""%2"".'"),
|
||
ИмяОбработчика,
|
||
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
|
||
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
ПроверитьВложеннуюТранзакцию(ТранзакцияАктивнаНаНачалоВыполнения, Обработчик.Процедура);
|
||
|
||
КонецЦикла;
|
||
|
||
Параметры = Новый Структура();
|
||
Параметры.Вставить("ВыполнитьОбновлениеСВерсии", Истина);
|
||
Параметры.Вставить("ВерсияКонфигурации", Метаданные.Версия);
|
||
Параметры.Вставить("ОчиститьСведенияОПредыдущейКонфигурации", Истина);
|
||
ПриЗавершенииПереходаСДругойПрограммы(ПредыдущееИмяКонфигурации, ПредыдущаяВерсияКонфигурации, Параметры);
|
||
|
||
// Установка текущих имени и версии конфигурации.
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
Если Параметры.ОчиститьСведенияОПредыдущейКонфигурации Тогда
|
||
Если ЭтоНеразделенныйСеанс Тогда
|
||
НаборЗаписей = РегистрыСведений.ВерсииПодсистем.СоздатьНаборЗаписей();
|
||
Иначе
|
||
НаборЗаписей = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ЗаписьВерсийПодсистемОбластейДанных();
|
||
КонецЕсли;
|
||
НаборЗаписей.Отбор.ИмяПодсистемы.Установить(ПредыдущееИмяКонфигурации);
|
||
НаборЗаписей.Записать();
|
||
КонецЕсли;
|
||
|
||
Если ЭтоНеразделенныйСеанс Тогда
|
||
НаборЗаписей = РегистрыСведений.ВерсииПодсистем.СоздатьНаборЗаписей();
|
||
Иначе
|
||
НаборЗаписей = МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ЗаписьВерсийПодсистемОбластейДанных();
|
||
КонецЕсли;
|
||
НаборЗаписей.Отбор.ИмяПодсистемы.Установить(Метаданные.Имя);
|
||
|
||
ВерсияКонфигурации = Метаданные.Версия;
|
||
Если Параметры.ВыполнитьОбновлениеСВерсии Тогда
|
||
ВерсияКонфигурации = Параметры.ВерсияКонфигурации;
|
||
КонецЕсли;
|
||
НоваяЗапись = НаборЗаписей.Добавить();
|
||
НоваяЗапись.ИмяПодсистемы = Метаданные.Имя;
|
||
НоваяЗапись.Версия = ВерсияКонфигурации;
|
||
Если ЭтоНеразделенныйСеанс Тогда
|
||
НоваяЗапись.ПланОбновления = Неопределено;
|
||
КонецЕсли;
|
||
НоваяЗапись.ЭтоОсновнаяКонфигурация = Истина;
|
||
|
||
НаборЗаписей.Записать();
|
||
ЗафиксироватьТранзакцию();
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
ОбновитьПовторноИспользуемыеЗначения();
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОбработчикНачальногоЗаполненияПредопределенных()
|
||
|
||
Возврат "ОбновлениеИнформационнойБазыСлужебный.НачальноеЗаполнениеПредопределенныхДанных";
|
||
|
||
КонецФункции
|
||
|
||
Процедура ПриЗавершенииПереходаСДругойПрограммы(ПредыдущееИмяКонфигурации, ПредыдущаяВерсияКонфигурации, Параметры)
|
||
|
||
ИмяКонфигурации = Метаданные.Имя;
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
Для каждого ИмяПодсистемы Из ОписанияПодсистем.Порядок Цикл
|
||
ОписаниеПодсистемы = ОписанияПодсистем.ПоИменам.Получить(ИмяПодсистемы); // см. СтандартныеПодсистемыПовтИсп.НовоеОписаниеПодсистемы
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеПодсистемы.ОсновнойСерверныйМодуль) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ОписаниеПодсистемы.Имя <> ИмяКонфигурации Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Модуль = ОбщегоНазначения.ОбщийМодуль(ОписаниеПодсистемы.ОсновнойСерверныйМодуль);
|
||
Модуль.ПриЗавершенииПереходаСДругойПрограммы(ПредыдущееИмяКонфигурации, ПредыдущаяВерсияКонфигурации, Параметры);
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ОбновлениеВерсииИБПередУдалениемСсылочногоОбъекта(Источник, Отказ) Экспорт
|
||
// АПК:75-выкл проверка ОбменДанными.Загрузка не требуется, т.к. данное событие
|
||
// должно выполняться всегда в процессе выполнения отложенного обновления.
|
||
|
||
Если ПолучитьФункциональнуюОпцию("ОтложенноеОбновлениеЗавершеноУспешно")
|
||
Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если Метаданные.ПланыОбмена.ОбновлениеИнформационнойБазы.Состав.Найти(Источник.Метаданные()) = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбновлениеИнформационнойБазы.Ссылка КАК Ссылка
|
||
|ИЗ
|
||
| ПланОбмена.ОбновлениеИнформационнойБазы КАК ОбновлениеИнформационнойБазы
|
||
|ГДЕ
|
||
| ОбновлениеИнформационнойБазы.ЭтотУзел = ЛОЖЬ";
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
Узлы = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
|
||
ПланыОбмена.УдалитьРегистрациюИзменений(Узлы, Источник);
|
||
КонецПроцедуры
|
||
|
||
Процедура УпорядочитьВерсииОбработчиков(ОбработчикиПоВерсиям)
|
||
ОбработчикиПоВерсиям.Колонки.Добавить("ВерсияПорядок", Новый ОписаниеТипов("Число"));
|
||
Для Каждого СтрокаВерсия Из ОбработчикиПоВерсиям.Строки Цикл
|
||
Версия = СтрокаВерсия.Версия;
|
||
Если Версия = "*" Или Не ЗначениеЗаполнено(Версия) Тогда
|
||
СтрокаВерсия.ВерсияПорядок = 0;
|
||
ИначеЕсли СтрНачинаетсяС(Версия, "ОтладкаОбработчика") Тогда
|
||
СтрокаВерсия.ВерсияПорядок = 99000000000;
|
||
Иначе
|
||
СтрокаВерсия.ВерсияПорядок = ВесВерсииИзМассиваСтрок(СтрРазделить(Версия, "."));
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
ОбработчикиПоВерсиям.Строки.Сортировать("ВерсияПорядок Возр");
|
||
КонецПроцедуры
|
||
|
||
Процедура ДобавитьОбработчики(ИмяБиблиотеки, ОбработчикиПоВерсиям, ДобавленныеОбработчики)
|
||
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборРазделенныхОбработчиков = РегистрыСведений.ОбработчикиОбновления.СоздатьНаборЗаписей();
|
||
НаборРазделенныхОбработчиков.Прочитать();
|
||
КонецЕсли;
|
||
Если Не ОбщегоНазначения.РазделениеВключено() Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборНеразделенныхОбработчиков = РегистрыСведений.ОбработчикиОбновленияОбщихДанных.СоздатьНаборЗаписей();
|
||
НаборНеразделенныхОбработчиков.Прочитать();
|
||
КонецЕсли;
|
||
|
||
Для Каждого Версия Из ОбработчикиПоВерсиям Цикл
|
||
Для Каждого Обработчик Из Версия.Строки Цикл
|
||
Если ДобавленныеОбработчики.Найти(Обработчик.ИмяОбработчика) <> Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.ОбщиеДанные = Истина Тогда
|
||
Запись = НаборНеразделенныхОбработчиков.Добавить();
|
||
Иначе
|
||
Запись = НаборРазделенныхОбработчиков.Добавить();
|
||
КонецЕсли;
|
||
|
||
ЗаполнитьЗначенияСвойств(Запись, Обработчик, , "РежимВыполнения");
|
||
|
||
Если Не ЗначениеЗаполнено(Обработчик.РежимВыполнения)
|
||
И (Обработчик.МонопольныйРежим = Истина Или Обработчик.МонопольныйРежим = Неопределено) Тогда
|
||
РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков.Монопольно;
|
||
ИначеЕсли Не ЗначениеЗаполнено(Обработчик.РежимВыполнения) И Обработчик.МонопольныйРежим = Ложь Тогда
|
||
РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков.Оперативно;
|
||
Иначе
|
||
РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков[Обработчик.РежимВыполнения];
|
||
КонецЕсли;
|
||
|
||
Запись.РежимВыполнения = РежимВыполнения;
|
||
Запись.Статус = Перечисления.СтатусыОбработчиковОбновления.НеВыполнялся;
|
||
Запись.ИмяБиблиотеки = ИмяБиблиотеки;
|
||
|
||
ДобавленныеОбработчики.Добавить(Обработчик.ИмяОбработчика);
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
|
||
// АПК:1327-выкл нет конкурентной работы с регистром
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборРазделенныхОбработчиков.Записать();
|
||
КонецЕсли;
|
||
Если Не ОбщегоНазначения.РазделениеВключено() Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборНеразделенныхОбработчиков.Записать();
|
||
КонецЕсли;
|
||
// АПК:1327-вкл
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УстановитьСтатусОбработчика(ИмяОбработчика, Статус, ТекстОшибки = "")
|
||
|
||
НаборЗаписей = Неопределено;
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборЗаписей = РегистрыСведений.ОбработчикиОбновления.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИмяОбработчика.Установить(ИмяОбработчика);
|
||
НаборЗаписей.Прочитать();
|
||
КонецЕсли;
|
||
|
||
ДоступноЧтениеНеразделенныхДанных = Не ОбщегоНазначения.РазделениеВключено()
|
||
Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
|
||
|
||
Если ДоступноЧтениеНеразделенныхДанных И (НаборЗаписей = Неопределено Или НаборЗаписей.Количество() = 0) Тогда
|
||
НаборЗаписей = РегистрыСведений.ОбработчикиОбновленияОбщихДанных.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИмяОбработчика.Установить(ИмяОбработчика);
|
||
НаборЗаписей.Прочитать();
|
||
КонецЕсли;
|
||
|
||
Если НаборЗаписей.Количество() = 0 Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Запись = НаборЗаписей[0];
|
||
Запись.Статус = Перечисления.СтатусыОбработчиковОбновления[Статус];
|
||
Запись.ИнформацияОбОшибке = ТекстОшибки;
|
||
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УстановитьСвойствоОбработчика(ИмяОбработчика, Свойство, Значение) Экспорт
|
||
|
||
Свойства = Новый Структура;
|
||
Свойства.Вставить(Свойство, Значение);
|
||
УстановитьСвойстваОбработчика(ИмяОбработчика, Свойства);
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УстановитьСвойстваОбработчика(ИмяОбработчика, Свойства)
|
||
|
||
Если Свойства.Количество() = 0 Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
НаборЗаписей = Неопределено;
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
НаборЗаписей = РегистрыСведений.ОбработчикиОбновления.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИмяОбработчика.Установить(ИмяОбработчика);
|
||
НаборЗаписей.Прочитать();
|
||
КонецЕсли;
|
||
|
||
ДоступноЧтениеНеразделенныхДанных = Не ОбщегоНазначения.РазделениеВключено()
|
||
Или Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
|
||
|
||
Если ДоступноЧтениеНеразделенныхДанных И (НаборЗаписей = Неопределено Или НаборЗаписей.Количество() = 0) Тогда
|
||
НаборЗаписей = РегистрыСведений.ОбработчикиОбновленияОбщихДанных.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИмяОбработчика.Установить(ИмяОбработчика);
|
||
НаборЗаписей.Прочитать();
|
||
КонецЕсли;
|
||
|
||
Если НаборЗаписей.Количество() = 0 Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Запись = НаборЗаписей[0];
|
||
Для Каждого Свойство Из Свойства Цикл
|
||
Запись[Свойство.Ключ] = Свойство.Значение;
|
||
КонецЦикла;
|
||
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Протоколирование хода обновления.
|
||
|
||
// Возвращает строковую константу для формирования сообщений журнала регистрации.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка
|
||
//
|
||
Функция СобытиеЖурналаРегистрации() Экспорт
|
||
|
||
Возврат НСтр("ru = 'Обновление информационной базы'", ОбщегоНазначения.КодОсновногоЯзыка());
|
||
|
||
КонецФункции
|
||
|
||
// Возвращает строковую константу для формирования сообщений журнала регистрации
|
||
// протоколирования хода выполнения обработчиков обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка
|
||
//
|
||
Функция СобытиеЖурналаРегистрацииПротокол() Экспорт
|
||
|
||
Возврат СобытиеЖурналаРегистрации() + "." + НСтр("ru = 'Протокол выполнения'", ОбщегоНазначения.КодОсновногоЯзыка());
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Описание обновлений
|
||
|
||
// Формирует табличный документ с описанием изменений в версиях,
|
||
// которые соответствуют переданному списку версий Разделы.
|
||
//
|
||
Функция ДокументОписаниеОбновлений(Знач Разделы) Экспорт
|
||
|
||
ДокументОписаниеОбновлений = Новый ТабличныйДокумент();
|
||
Если Разделы.Количество() = 0 Тогда
|
||
Возврат ДокументОписаниеОбновлений;
|
||
КонецЕсли;
|
||
|
||
МакетОписаниеОбновлений = Метаданные.ОбщиеМакеты.Найти("ОписаниеИзмененийСистемы");
|
||
Если МакетОписаниеОбновлений <> Неопределено Тогда
|
||
МакетОписаниеОбновлений = ПолучитьОбщийМакет(МакетОписаниеОбновлений);
|
||
Иначе
|
||
Возврат Новый ТабличныйДокумент();
|
||
КонецЕсли;
|
||
|
||
Для Каждого Версия Из Разделы Цикл
|
||
|
||
ВывестиОписаниеИзменений(Версия, ДокументОписаниеОбновлений, МакетОписаниеОбновлений);
|
||
|
||
КонецЦикла;
|
||
|
||
Возврат ДокументОписаниеОбновлений;
|
||
|
||
КонецФункции
|
||
|
||
// Возвращает массив версий больше последней отображавшейся версии,
|
||
// для которых есть описания изменений системы.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Массив - содержит строки с версиями.
|
||
//
|
||
Функция НеотображавшиесяРазделыОписанияИзменений() Экспорт
|
||
|
||
Разделы = РазделыОписанияИзменений();
|
||
|
||
ПоследняяВерсия = ПоследняяВерсияОтображенияИзмененийСистемы();
|
||
|
||
Если ПоследняяВерсия = Неопределено Тогда
|
||
Возврат Новый Массив;
|
||
КонецЕсли;
|
||
|
||
Возврат ПолучитьВерсииБольшеЗаданной(Разделы, ПоследняяВерсия);
|
||
|
||
КонецФункции
|
||
|
||
// Устанавливает флаг отображения описаний изменений версий по
|
||
// текущую версию включительно.
|
||
//
|
||
// Параметры:
|
||
// ИмяПользователя - Строка - имя пользователя, для которого
|
||
// необходимо установить флаг.
|
||
//
|
||
Процедура УстановитьФлагОтображенияОписанийПоТекущуюВерсию(Знач ИмяПользователя = Неопределено) Экспорт
|
||
|
||
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить("ОбновлениеИБ",
|
||
"ПоследняяВерсияОтображенияИзмененийСистемы", Метаданные.Версия, , ИмяПользователя);
|
||
|
||
Если ИмяПользователя = Неопределено И Пользователи.ЭтоПолноправныйПользователь() Тогда
|
||
|
||
ОбщегоНазначения.ХранилищеОбщихНастроекУдалить("ОбновлениеИБ", "ВывестиОписаниеИзмененийДляАдминистратора", ИмяПользователя());
|
||
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Механизм отложенного обновления.
|
||
|
||
// Планирует выполнение отложенного обновления в клиент-серверной базе.
|
||
//
|
||
Процедура ЗапланироватьОтложенноеОбновление()
|
||
|
||
// Планирование выполнения регламентного задания.
|
||
// При работе в модели сервиса - добавляется регламентное задание в очередь.
|
||
Если Не ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
|
||
ПриВключенииОтложенногоОбновления(Истина);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Управляет процессом выполнения отложенных обработчиков обновления.
|
||
//
|
||
Процедура ВыполнитьОтложенноеОбновление() Экспорт
|
||
|
||
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания();
|
||
|
||
Если ОбновлениеИнформационнойБазыСлужебныйПовтИсп.НеобходимоОбновлениеИнформационнойБазы() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
|
||
Если СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления <> Неопределено Тогда
|
||
ОтключитьОтложенноеОбновление();
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если СведенияОбОбновлении.ВремяНачалаОтложенногоОбновления = Неопределено Тогда
|
||
СведенияОбОбновлении.ВремяНачалаОтложенногоОбновления = ТекущаяДатаСеанса();
|
||
КонецЕсли;
|
||
Если ТипЗнч(СведенияОбОбновлении.НомерСеанса) <> Тип("СписокЗначений") Тогда
|
||
СведенияОбОбновлении.НомерСеанса = Новый СписокЗначений;
|
||
КонецЕсли;
|
||
СведенияОбОбновлении.НомерСеанса.Добавить(НомерСеансаИнформационнойБазы());
|
||
СведенияОбОбновлении.ДатаНачалаСеансаОбновления = ТекущаяДатаСеанса();
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
// В сеансе регламентного задания проверка дат запрета изменения и загрузки отключается.
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ДатыЗапретаИзменения") Тогда
|
||
МодульДатыЗапретаИзменения = ОбщегоНазначения.ОбщийМодуль("ДатыЗапретаИзменения");
|
||
МодульДатыЗапретаИзменения.ОтключитьПроверкуДатЗапрета(Истина);
|
||
КонецЕсли;
|
||
|
||
ОбработчикиВыполнялись = Истина;
|
||
|
||
ДатаПоследнейПроверки = Неопределено;
|
||
Попытка
|
||
Если ФорсироватьОбновление(СведенияОбОбновлении) Тогда
|
||
Группы = НовоеОписаниеГруппПотоковОбработчиковОтложенногоОбновления();
|
||
ОтменитьВыполнениеВсехПотоков(Группы);
|
||
|
||
Пока ОбработчикиВыполнялись Цикл
|
||
Поток = ДобавитьПотокОбработчикаОтложенногоОбновления(СведенияОбОбновлении);
|
||
Если ТипЗнч(Поток) = Тип("СтрокаТаблицыЗначений") Тогда
|
||
ВыполнитьПоток(Группы, Поток);
|
||
ОжидатьСвободныйПоток(Группы);
|
||
ИначеЕсли Поток = Истина Тогда
|
||
ОжидатьЗавершениеЛюбогоПотока(Группы);
|
||
ИначеЕсли Поток = Ложь Тогда
|
||
ОбработчикиВыполнялись = Ложь;
|
||
ОжидатьЗавершениеВсехПотоков(Группы);
|
||
Прервать;
|
||
КонецЕсли;
|
||
|
||
Если ДатаПоследнейПроверки = Неопределено
|
||
Или ТекущаяДатаСеанса() - ДатаПоследнейПроверки > 600 Тогда
|
||
ДатаПоследнейПроверки = ТекущаяДатаСеанса();
|
||
ОчиститьПрогрессОбработкиЗаИнтервалыПредыдущегоДня();
|
||
КонецЕсли;
|
||
|
||
Задание = РегламентныеЗаданияСервер.Задание(Метаданные.РегламентныеЗадания.ОтложенноеОбновлениеИБ);
|
||
ТребуетсяВыполнение = Задание.Расписание.ТребуетсяВыполнение(ТекущаяДатаСеанса());
|
||
|
||
Если Не ТребуетсяВыполнение Или Не ФорсироватьОбновление(СведенияОбОбновлении) Тогда
|
||
ОжидатьЗавершениеВсехПотоков(Группы);
|
||
УдалитьВсеПотокиОбновления();
|
||
Прервать;
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
Иначе
|
||
ОчиститьПрогрессОбработкиЗаИнтервалыПредыдущегоДня();
|
||
ОбработчикиВыполнялись = ВыполнитьОтложенныйОбработчикОбновления();
|
||
КонецЕсли;
|
||
Исключение
|
||
ЗаписатьОшибку(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
|
||
ОтменитьВыполнениеВсехПотоков(Группы);
|
||
УдалитьВсеПотокиОбновления();
|
||
КонецПопытки;
|
||
|
||
Если Не ОбработчикиВыполнялись Или ВыполненыВсеОтложенныеОбработчики(СведенияОбОбновлении) Тогда
|
||
УдалитьВсеПотокиОбновления();
|
||
ОтключитьОтложенноеОбновление();
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ОчиститьПрогрессОбработкиЗаИнтервалыПредыдущегоДня()
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("ИнтервалЧас", НачалоДня(ТекущаяДатаСеанса()));
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ПрогрессОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ПрогрессОбновления.ИнтервалЧас КАК ИнтервалЧас,
|
||
| ПрогрессОбновления.КлючЗаписи КАК КлючЗаписи
|
||
|ИЗ
|
||
| РегистрСведений.ПрогрессОбновления КАК ПрогрессОбновления
|
||
|ГДЕ
|
||
| ПрогрессОбновления.ИнтервалЧас < &ИнтервалЧас";
|
||
Результат = Запрос.Выполнить().Выгрузить();
|
||
|
||
Для Каждого Строка Из Результат Цикл
|
||
МенеджерЗаписи = РегистрыСведений.ПрогрессОбновления.СоздатьМенеджерЗаписи();
|
||
МенеджерЗаписи.ИмяОбработчика = Строка.ИмяОбработчика;
|
||
МенеджерЗаписи.ИнтервалЧас = Строка.ИнтервалЧас;
|
||
МенеджерЗаписи.КлючЗаписи = Строка.КлючЗаписи;
|
||
МенеджерЗаписи.Удалить();
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОбработчикиДляОтложеннойРегистрацииДанных(БезФильтра = Ложь, ПерезапускОбновления = Ложь, РегистрируемыеОбработчики = Неопределено) Экспорт
|
||
|
||
Если РегистрируемыеОбработчики = Неопределено Тогда
|
||
РегистрируемыеОбработчики = Новый Массив;
|
||
КонецЕсли;
|
||
|
||
ЭтоПодчиненныйУзелРИБСФильтром = ОбщегоНазначения.ЭтоПодчиненныйУзелРИБСФильтром();
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполненияОбработчика", Перечисления.РежимыВыполненияОтложенныхОбработчиков.Параллельно);
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("БезФильтра", БезФильтра);
|
||
Запрос.УстановитьПараметр("ЭтоПодчиненныйУзелРИБСФильтром", ЭтоПодчиненныйУзелРИБСФильтром);
|
||
// Отборы для перезапуска отложенного обновления.
|
||
Запрос.УстановитьПараметр("СтатусОбработчика", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.УстановитьПараметр("РегистрируемыеОбработчики", РегистрируемыеОбработчики);
|
||
Запрос.УстановитьПараметр("ОтключитьОтбор", (Не ПерезапускОбновления Или РегистрируемыеОбработчики.Количество() = 0));
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.ИмяБиблиотеки КАК ИмяБиблиотеки,
|
||
| ОбработчикиОбновления.Версия КАК Версия,
|
||
| ОбработчикиОбновления.ПроцедураЗаполненияДанныхОбновления КАК ПроцедураЗаполненияДанныхОбновления,
|
||
| ОбработчикиОбновления.ОчередьОтложеннойОбработки КАК ОчередьОтложеннойОбработки,
|
||
| ОбработчикиОбновления.Многопоточный КАК Многопоточный,
|
||
| ОбработчикиОбновления.ОбрабатываемыеДанные КАК ОбрабатываемыеДанные,
|
||
| ОбработчикиОбновления.Статус КАК Статус
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И (ОбработчикиОбновления.РежимВыполненияОтложенногоОбработчика = &РежимВыполненияОбработчика
|
||
| ИЛИ &БезФильтра)
|
||
| И (ОбработчикиОбновления.Статус <> &СтатусОбработчика
|
||
| ИЛИ ОбработчикиОбновления.ИмяОбработчика В(&РегистрируемыеОбработчики)
|
||
| ИЛИ &ОтключитьОтбор)
|
||
| И (&ЭтоПодчиненныйУзелРИБСФильтром
|
||
| И ОбработчикиОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами
|
||
| ИЛИ НЕ &ЭтоПодчиненныйУзелРИБСФильтром)
|
||
|
|
||
|УПОРЯДОЧИТЬ ПО
|
||
| ОбработчикиОбновления.ОчередьОтложеннойОбработки";
|
||
Обработчики = Запрос.Выполнить().Выгрузить();
|
||
|
||
Возврат Обработчики;
|
||
|
||
КонецФункции
|
||
|
||
Функция НайтиОбработчикОбновления(КонтекстОбработчика, ПараметрыОбновления = Неопределено)
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
|
||
// Получение групп, по которым еще не выполнены все обработчики обновления.
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ РАЗЛИЧНЫЕ
|
||
| ОбработчикиОбновления.ГруппаОбновления КАК ГруппаОбновления
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.Статус <> &Статус
|
||
| И ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения";
|
||
ГруппыОбработчиковИЗависимость = Запрос.Выполнить().Выгрузить();
|
||
|
||
// Выбор невыполненных обработчиков обновления.
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.Статус КАК Статус,
|
||
| ОбработчикиОбновления.Версия КАК Версия,
|
||
| ОбработчикиОбновления.ИмяБиблиотеки КАК ИмяБиблиотеки,
|
||
| ОбработчикиОбновления.ДлительностьОбработки КАК ДлительностьОбработки,
|
||
| ОбработчикиОбновления.РежимВыполнения КАК РежимВыполнения,
|
||
| ОбработчикиОбновления.ВерсияРегистрации КАК ВерсияРегистрации,
|
||
| ОбработчикиОбновления.ВерсияПорядок КАК ВерсияПорядок,
|
||
| ОбработчикиОбновления.Идентификатор КАК Идентификатор,
|
||
| ОбработчикиОбновления.ЧислоПопыток КАК ЧислоПопыток,
|
||
| ОбработчикиОбновления.ИнформацияОбОшибке КАК ИнформацияОбОшибке,
|
||
| ОбработчикиОбновления.Комментарий КАК Комментарий,
|
||
| ОбработчикиОбновления.Приоритет КАК Приоритет,
|
||
| ОбработчикиОбновления.ПроцедураПроверки КАК ПроцедураПроверки,
|
||
| ОбработчикиОбновления.ПроцедураЗаполненияДанныхОбновления КАК ПроцедураЗаполненияДанныхОбновления,
|
||
| ОбработчикиОбновления.ОчередьОтложеннойОбработки КАК ОчередьОтложеннойОбработки,
|
||
| ОбработчикиОбновления.ЗапускатьТолькоВГлавномУзле КАК ЗапускатьТолькоВГлавномУзле,
|
||
| ОбработчикиОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами КАК ЗапускатьИВПодчиненномУзлеРИБСФильтрами,
|
||
| ОбработчикиОбновления.Многопоточный КАК Многопоточный,
|
||
| ОбработчикиОбновления.ОбработкаПорцииЗавершена КАК ОбработкаПорцииЗавершена,
|
||
| ОбработчикиОбновления.ГруппаОбновления КАК ГруппаОбновления,
|
||
| ОбработчикиОбновления.ИтерацияЗапуска КАК ИтерацияЗапуска,
|
||
| ОбработчикиОбновления.ОбрабатываемыеДанные КАК ОбрабатываемыеДанные,
|
||
| ОбработчикиОбновления.СтатистикаВыполнения КАК СтатистикаВыполнения,
|
||
| ОбработчикиОбновления.РежимВыполненияОтложенногоОбработчика КАК РежимВыполненияОтложенногоОбработчика,
|
||
| ОбработчикиОбновления.ИзменяемыеОбъекты КАК ИзменяемыеОбъекты
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.Статус <> &Статус
|
||
|
|
||
|УПОРЯДОЧИТЬ ПО
|
||
| ГруппаОбновления,
|
||
| ОчередьОтложеннойОбработки";
|
||
Обработчики = Запрос.Выполнить().Выгрузить();
|
||
|
||
Пока Истина Цикл
|
||
Результат = ОбработчикДляВыполнения(Обработчики, ГруппыОбработчиковИЗависимость, СведенияОбОбновлении);
|
||
Если Результат.ОбработчикДляВыполнения = Неопределено
|
||
И Результат.ЕстьНевыполненные
|
||
И Не Результат.ПрерватьВыполнение Тогда
|
||
СведенияОбОбновлении.ТекущаяИтерацияОбновления = СведенияОбОбновлении.ТекущаяИтерацияОбновления + 1;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
Иначе
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
ОбработчикДляВыполнения = Результат.ОбработчикДляВыполнения;
|
||
Если ОбработчикДляВыполнения = Неопределено Или Результат.ПрерватьВыполнение Тогда
|
||
Если Результат.ЕстьВыполняющиеся И Не Результат.ПрерватьВыполнение Тогда
|
||
Возврат Истина;
|
||
Иначе
|
||
СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления = ТекущаяДатаСеанса();
|
||
СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно = Результат.ЗавершеноУспешно;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
Константы.ОтложенноеОбновлениеЗавершеноУспешно.Установить(Результат.ЗавершеноУспешно);
|
||
Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
|
||
Константы.ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.Установить(Результат.ЗавершеноУспешно);
|
||
КонецЕсли;
|
||
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ПараллельныйРежим = (ОбработчикДляВыполнения.РежимВыполненияОтложенногоОбработчика = Перечисления.РежимыВыполненияОтложенныхОбработчиков.Параллельно);
|
||
ПараметрыОбновления = ?(ПараметрыОбновления = Неопределено, Новый Структура, ПараметрыОбновления);
|
||
ПараметрыОбновления.Вставить("ПараллельныйРежим", ПараллельныйРежим);
|
||
Если ПараллельныйРежим Тогда
|
||
ПараметрыОбновления.Вставить("ОчередьОбработчиков", ОчередьОбработчиковГруппыОбновления(ОбработчикДляВыполнения.ГруппаОбновления));
|
||
ПараметрыОбновления.Вставить("ЕстьОбработчикиГлавногоУзла", ЕстьОбработчикиТолькоГлавногоУзла());
|
||
КонецЕсли;
|
||
|
||
УстановитьПараметрыОбработчикаОбновления(ОбработчикДляВыполнения, Истина, ПараллельныйРежим);
|
||
ПередЗапускомПроцедурыОбработкиДанных(КонтекстОбработчика,
|
||
ОбработчикДляВыполнения,
|
||
ПараметрыОбновления,
|
||
СведенияОбОбновлении);
|
||
|
||
КонтекстОбработчика.ИдентификаторОбработчика = ОбработчикДляВыполнения.Идентификатор;
|
||
КонтекстОбработчика.ИмяОбработчика = ОбработчикДляВыполнения.ИмяОбработчика;
|
||
КонтекстОбработчика.ПараллельныйРежим = ПараллельныйРежим;
|
||
КонтекстОбработчика.ПараметрыОбновления = ПараметрыОбновления;
|
||
КонтекстОбработчика.ПараметрыОбработчикаОбновления = ПараметрыСеанса.ПараметрыОбработчикаОбновления;
|
||
КонтекстОбработчика.ТекущаяИтерацияОбновления = СведенияОбОбновлении.ТекущаяИтерацияОбновления;
|
||
|
||
УстановитьПараметрыОбработчикаОбновления(Неопределено);
|
||
|
||
Возврат ОбработчикДляВыполнения;
|
||
|
||
КонецФункции
|
||
|
||
Процедура СброситьСведенияОбОбновлении(СведенияОбОбновлении)
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Константы.ОтложенноеОбновлениеЗавершеноУспешно.Установить(Ложь);
|
||
|
||
СведенияОбОбновлении.Вставить("ВремяНачалаОбновления");
|
||
СведенияОбОбновлении.Вставить("ВремяОкончанияОбновления");
|
||
СведенияОбОбновлении.Вставить("ПродолжительностьОбновления");
|
||
СведенияОбОбновлении.Вставить("ВремяНачалаОтложенногоОбновления");
|
||
СведенияОбОбновлении.Вставить("ВремяОкончаниеОтложенногоОбновления");
|
||
СведенияОбОбновлении.Вставить("НомерСеанса", Новый СписокЗначений());
|
||
СведенияОбОбновлении.Вставить("ОтложенноеОбновлениеЗавершеноУспешно");
|
||
СведенияОбОбновлении.Вставить("ВыводитьОписаниеОбновлений", Ложь);
|
||
СведенияОбОбновлении.Вставить("ПриостановленныеПроцедурыОбновления", Новый Массив);
|
||
СведенияОбОбновлении.Вставить("ЗапущенныеПроцедурыОбновления", Новый Массив);
|
||
Если СведенияОбОбновлении.УправлениеОтложеннымОбновлением.Свойство("ФорсироватьОбновление") Тогда
|
||
СведенияОбОбновлении.Вставить("УправлениеОтложеннымОбновлением", Новый Структура("ФорсироватьОбновление"));
|
||
Иначе
|
||
СведенияОбОбновлении.Вставить("УправлениеОтложеннымОбновлением", Новый Структура);
|
||
КонецЕсли;
|
||
СведенияОбОбновлении.Вставить("ТекущаяИтерацияОбновления", 1);
|
||
СведенияОбОбновлении.Вставить("ЗависимостьГруппОбработчиков", Новый Соответствие);
|
||
СведенияОбОбновлении.ВерсияДереваОбработчиков = Метаданные.Версия;
|
||
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
ЗаписатьСведенияОБлокируемыхОбъектах(НовыеСведенияОБлокируемыхОбъектах());
|
||
КонецПроцедуры
|
||
|
||
Процедура ПроверитьСвойстваОтложенногоОбработчика(Знач Обработчик, Знач РежимВыполненияОтложенныхОбработчиков, ТекстОшибок)
|
||
|
||
Если РежимВыполненияОтложенныхОбработчиков = "Параллельно"
|
||
И Не ЗначениеЗаполнено(Обработчик.ПроцедураЗаполненияДанныхОбновления) Тогда
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Не указана процедура заполнения данных
|
||
|отложенного обработчика обновления
|
||
|""%1"".'"),
|
||
Обработчик.ИмяОбработчика);
|
||
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
ТекстОшибок = ТекстОшибок + ТекстОшибки + Символы.ПС;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.МонопольныйРежим = Истина Тогда
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'У отложенного обработчика ""%1""
|
||
|не должен быть установлен признак ""%2"".'"),
|
||
Обработчик.ИмяОбработчика,
|
||
"МонопольныйРежим");
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
ТекстОшибок = ТекстОшибок + ТекстОшибки + Символы.ПС;
|
||
КонецЕсли;
|
||
|
||
Если РежимВыполненияОтложенныхОбработчиков = "Параллельно" И Обработчик.ЗапускатьТолькоВГлавномУзле
|
||
И Обработчик.ЗапускатьИВПодчиненномУзлеРИБСФильтрами Тогда
|
||
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'У отложенного обработчика ""%1""
|
||
|некорректно заполнены значения свойств:
|
||
| - ""%2""
|
||
| - ""%3"".
|
||
|
|
||
|Данные свойства не могут одновременно принимать значение ""Истина"".'"),
|
||
Обработчик.ИмяОбработчика,
|
||
"ЗапускатьТолькоВГлавномУзле",
|
||
"ЗапускатьИВПодчиненномУзлеРИБСФильтрами");
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
ТекстОшибок = ТекстОшибок + ТекстОшибки + Символы.ПС;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.ОбщиеДанные = Истина Тогда
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'У отложенного обработчика ""%1""
|
||
|указано недопустимое значение свойства ""%2"".
|
||
|
|
||
|Данное свойство не может принимать значение ""Истина"" у отложенного обработчика.'"),
|
||
Обработчик.ИмяОбработчика, "ОбщиеДанные");
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
ТекстОшибок = ТекстОшибок + ТекстОшибки + Символы.ПС;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ПроверитьУникальностьИдентификаторовОтложенныхОбработчиков(ИтерацииОбновления)
|
||
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
ТаблицаПроверкиУникальности = Новый ТаблицаЗначений;
|
||
ТаблицаПроверкиУникальности.Колонки.Добавить("Идентификатор");
|
||
ТаблицаПроверкиУникальности.Колонки.Добавить("Индекс");
|
||
|
||
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
|
||
|
||
ПараметрыОтбора = Новый Структура;
|
||
ПараметрыОтбора.Вставить("РежимВыполнения", "Отложенно");
|
||
ТаблицаОбработчиков = ИтерацияОбновления.Обработчики;
|
||
|
||
Обработчики = ТаблицаОбработчиков.НайтиСтроки(ПараметрыОтбора);
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
Если Не ЗначениеЗаполнено(Обработчик.Идентификатор) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
СтрокаТаблицы = ТаблицаПроверкиУникальности.Добавить();
|
||
СтрокаТаблицы.Идентификатор = Строка(Обработчик.Идентификатор);
|
||
СтрокаТаблицы.Индекс = 1;
|
||
КонецЦикла;
|
||
|
||
КонецЦикла;
|
||
|
||
ИсходноеКоличествоСтрок = ТаблицаПроверкиУникальности.Количество();
|
||
ТаблицаПроверкиУникальности.Свернуть("Идентификатор", "Индекс");
|
||
ИтоговоеКоличествоСтрок = ТаблицаПроверкиУникальности.Количество();
|
||
|
||
// Быстрая проверка.
|
||
Если ИсходноеКоличествоСтрок = ИтоговоеКоличествоСтрок Тогда
|
||
Возврат; // Все идентификаторы уникальны.
|
||
КонецЕсли;
|
||
|
||
ТаблицаПроверкиУникальности.Сортировать("Индекс Убыв");
|
||
ТекстСообщения = НСтр("ru = 'Обнаружены отложенные обработчики обновления,
|
||
|у которых совпадают уникальные идентификаторы. Следующие идентификаторы не уникальны:'");
|
||
Для Каждого СтрокаИдентификатор Из ТаблицаПроверкиУникальности Цикл
|
||
Если СтрокаИдентификатор.Индекс = 1 Тогда
|
||
Прервать;
|
||
Иначе
|
||
ТекстСообщения = ТекстСообщения + Символы.ПС + СтрокаИдентификатор.Идентификатор;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
ВызватьИсключение ТекстСообщения;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ДобавитьОтложенныеОбработчики(ИмяБиблиотеки, ОбработчикиПоВерсиям, ГруппаОбновления, ТекстОшибок, ТекущийРежимВыполнения = "")
|
||
|
||
ЭтоПодчиненныйУзелРИБ = ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ();
|
||
ЭтоПодчиненныйУзелРИБСФильтром = ОбщегоНазначения.ЭтоПодчиненныйУзелРИБСФильтром();
|
||
ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
|
||
|
||
ОписаниеПодсистемы = ОписанияПодсистем.ПоИменам[ИмяБиблиотеки];
|
||
ПараллельноСВерсии = ОписаниеПодсистемы.ПараллельноеОтложенноеОбновлениеСВерсии;
|
||
РежимВыполненияОтложенныхОбработчиков = ОписаниеПодсистемы.РежимВыполненияОтложенныхОбработчиков;
|
||
|
||
НаборРазделенныхОбработчиков = РегистрыСведений.ОбработчикиОбновления.СоздатьНаборЗаписей();
|
||
НаборРазделенныхОбработчиков.Прочитать();
|
||
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
ЗависимостьГруппОбработчиков = СведенияОбОбновлении.ЗависимостьГруппОбработчиков;
|
||
|
||
ПропуститьПроверку = Ложь;
|
||
СоздаватьНовуюИтерацию = Истина;
|
||
Итерация = 1;
|
||
ЕстьОбработчикиТолькоГлавногоУзла = Ложь;
|
||
СведенияОБлокируемыхОбъектах = СведенияОБлокируемыхОбъектах();
|
||
Для Каждого СтрокаВерсия Из ОбработчикиПоВерсиям Цикл
|
||
ЗаполнитьБлокируемыеОбъекты(СтрокаВерсия, СведенияОБлокируемыхОбъектах);
|
||
|
||
Если РежимВыполненияОтложенныхОбработчиков = "Последовательно" Тогда
|
||
Если ТекущийРежимВыполнения = "Параллельно" Тогда
|
||
// У предыдущей библиотеки был параллельный режим, поэтому
|
||
// для текущей создаем отдельную группу обновления.
|
||
ГруппаОбновления = ГруппаОбновления + 1;
|
||
КонецЕсли;
|
||
ЗависимостьГруппОбработчиков.Вставить(ГруппаОбновления, Итерация <> 1);
|
||
ТекущийРежимВыполнения = "Последовательно";
|
||
ИначеЕсли РежимВыполненияОтложенныхОбработчиков = "Параллельно" И Не ЗначениеЗаполнено(ПараллельноСВерсии) Тогда
|
||
ЗависимостьГруппОбработчиков.Вставить(ГруппаОбновления, Ложь);
|
||
ТекущийРежимВыполнения = "Параллельно";
|
||
СоздаватьНовуюИтерацию = Ложь;
|
||
ИначеЕсли РежимВыполненияОтложенныхОбработчиков = "Параллельно" И ЗначениеЗаполнено(ПараллельноСВерсии) И Не ПропуститьПроверку Тогда
|
||
НомерВерсии = СтрокаВерсия.Версия;
|
||
Если НомерВерсии = "*" Тогда
|
||
Результат = -1;
|
||
ИначеЕсли СтрНачинаетсяС(НомерВерсии, "ОтладкаОбработчика") Тогда
|
||
Результат = 1;
|
||
Иначе
|
||
Результат = ОбщегоНазначенияКлиентСервер.СравнитьВерсии(НомерВерсии, ПараллельноСВерсии);
|
||
КонецЕсли;
|
||
|
||
Если Результат < 0 Тогда
|
||
Если ТекущийРежимВыполнения = "Параллельно" Тогда
|
||
// У предыдущей библиотеки был параллельный режим, поэтому
|
||
// для текущей создаем отдельную группу обновления.
|
||
ГруппаОбновления = ГруппаОбновления + 1;
|
||
КонецЕсли;
|
||
ЗависимостьГруппОбработчиков.Вставить(ГруппаОбновления, Итерация <> 1);
|
||
ТекущийРежимВыполнения = "Последовательно";
|
||
Иначе
|
||
ЗависимостьГруппОбработчиков.Вставить(ГруппаОбновления, Итерация <> 1);
|
||
ПропуститьПроверку = Истина;
|
||
ТекущийРежимВыполнения = "Параллельно";
|
||
СоздаватьНовуюИтерацию = Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Для Каждого Обработчик Из СтрокаВерсия.Строки Цикл
|
||
ПроверитьСвойстваОтложенногоОбработчика(Обработчик, ТекущийРежимВыполнения, ТекстОшибок);
|
||
|
||
Запись = НаборРазделенныхОбработчиков.Добавить();
|
||
|
||
ЗаполнитьЗначенияСвойств(Запись, Обработчик, , "РежимВыполнения,ВерсияПорядок");
|
||
РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков[Обработчик.РежимВыполнения];
|
||
|
||
Запись.ВерсияПорядок = СтрокаВерсия.ВерсияПорядок;
|
||
Запись.РежимВыполнения = РежимВыполнения;
|
||
Запись.Статус = Перечисления.СтатусыОбработчиковОбновления.НеВыполнялся;
|
||
Запись.ИмяБиблиотеки = ИмяБиблиотеки;
|
||
Запись.ГруппаОбновления = ГруппаОбновления;
|
||
Запись.СтатистикаВыполнения = Новый ХранилищеЗначения(Новый Соответствие);
|
||
Если ТекущийРежимВыполнения = "Параллельно" Тогда
|
||
Запись.РежимВыполненияОтложенногоОбработчика = Перечисления.РежимыВыполненияОтложенныхОбработчиков.Параллельно;
|
||
Иначе
|
||
Запись.РежимВыполненияОтложенногоОбработчика = Перечисления.РежимыВыполненияОтложенныхОбработчиков.Последовательно;
|
||
КонецЕсли;
|
||
|
||
// Определение значения константы ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.
|
||
Если ТекущийРежимВыполнения = "Параллельно" И Не ЭтоПодчиненныйУзелРИБ
|
||
И Обработчик.ЗапускатьТолькоВГлавномУзле = Истина Тогда
|
||
ЕстьОбработчикиТолькоГлавногоУзла = Истина;
|
||
КонецЕсли;
|
||
Если ТекущийРежимВыполнения = "Параллельно" И ЭтоПодчиненныйУзелРИБСФильтром
|
||
И Не Обработчик.ЗапускатьИВПодчиненномУзлеРИБСФильтрами Тогда
|
||
ЕстьОбработчикиТолькоГлавногоУзла = Истина;
|
||
// В подчиненном узле РИБ обработчики главного узла не выполняются.
|
||
Запись.Статус = Перечисления.СтатусыОбработчиковОбновления.Выполнен;
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
Если СоздаватьНовуюИтерацию Тогда
|
||
ГруппаОбновления = ГруппаОбновления + 1;
|
||
КонецЕсли;
|
||
Итерация = Итерация + 1;
|
||
КонецЦикла;
|
||
|
||
ЗаписатьСведенияОБлокируемыхОбъектах(СведенияОБлокируемыхОбъектах);
|
||
ТекущееЗначение = Константы.ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.Получить();
|
||
Константы.ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.Установить(ТекущееЗначение И Не ЕстьОбработчикиТолькоГлавногоУзла);
|
||
|
||
// АПК:1327-выкл нет конкурентной работы с регистром
|
||
НаборРазделенныхОбработчиков.Записать();
|
||
// АПК:1327-вкл
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция НезавершенныеОтложенныеОбработчики(СведенияОбОбновлении)
|
||
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.Статус КАК Статус,
|
||
| ОбработчикиОбновления.Версия КАК Версия,
|
||
| ОбработчикиОбновления.ИмяБиблиотеки КАК ИмяБиблиотеки,
|
||
| ОбработчикиОбновления.ДлительностьОбработки КАК ДлительностьОбработки,
|
||
| ОбработчикиОбновления.РежимВыполнения КАК РежимВыполнения,
|
||
| ОбработчикиОбновления.ВерсияРегистрации КАК ВерсияРегистрации,
|
||
| ОбработчикиОбновления.Идентификатор КАК Идентификатор,
|
||
| ОбработчикиОбновления.ЧислоПопыток КАК ЧислоПопыток,
|
||
| ОбработчикиОбновления.СтатистикаВыполнения КАК СтатистикаВыполнения,
|
||
| ОбработчикиОбновления.ИнформацияОбОшибке КАК ИнформацияОбОшибке,
|
||
| ОбработчикиОбновления.Комментарий КАК Комментарий,
|
||
| ОбработчикиОбновления.Приоритет КАК Приоритет,
|
||
| ОбработчикиОбновления.ПроцедураПроверки КАК ПроцедураПроверки,
|
||
| ОбработчикиОбновления.ПроцедураЗаполненияДанныхОбновления КАК ПроцедураЗаполненияДанныхОбновления,
|
||
| ОбработчикиОбновления.ОчередьОтложеннойОбработки КАК ОчередьОтложеннойОбработки,
|
||
| ОбработчикиОбновления.ЗапускатьТолькоВГлавномУзле КАК ЗапускатьТолькоВГлавномУзле,
|
||
| ОбработчикиОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами КАК ЗапускатьИВПодчиненномУзлеРИБСФильтрами,
|
||
| ОбработчикиОбновления.Многопоточный КАК Многопоточный,
|
||
| ОбработчикиОбновления.ОбработкаПорцииЗавершена КАК ОбработкаПорцииЗавершена,
|
||
| ОбработчикиОбновления.ГруппаОбновления КАК ГруппаОбновления,
|
||
| ОбработчикиОбновления.ИтерацияЗапуска КАК ИтерацияЗапуска,
|
||
| ОбработчикиОбновления.ОбрабатываемыеДанные КАК ОбрабатываемыеДанные
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.Статус <> &Статус";
|
||
Обработчики = Запрос.Выполнить().Выгрузить();
|
||
|
||
ДеревоОбработчиков = СведенияОбОбновлении.ДеревоОбработчиков.Строки;
|
||
Если ДеревоОбработчиков.Количество() > 0 Тогда
|
||
СведенияОбОбновлении.ДеревоОбработчиков.Колонки.НомерВерсии.Имя = "Версия";
|
||
Отбор = Новый Структура;
|
||
Отбор.Вставить("Статус", "Выполняется");
|
||
Выполняются = ДеревоОбработчиков.НайтиСтроки(Отбор, Истина);
|
||
ПеренестиОбработчикиИзКонстанты(Обработчики, Выполняются);
|
||
|
||
Отбор.Статус = "НеВыполнено";
|
||
НеВыполнены = ДеревоОбработчиков.НайтиСтроки(Отбор, Истина);
|
||
ПеренестиОбработчикиИзКонстанты(Обработчики, НеВыполнены);
|
||
|
||
Отбор.Статус = "Ошибка";
|
||
ЗавершилисьСОшибкой = ДеревоОбработчиков.НайтиСтроки(Отбор, Истина);
|
||
ПеренестиОбработчикиИзКонстанты(Обработчики, ЗавершилисьСОшибкой);
|
||
|
||
СведенияОбОбновлении.ДеревоОбработчиков = Новый ДеревоЗначений;
|
||
КонецЕсли;
|
||
|
||
Возврат Обработчики
|
||
|
||
КонецФункции
|
||
|
||
Процедура ДобавитьНезавершенныеОтложенныеОбработчики(ИтерацияОбновления, ИмяБиблиотеки,
|
||
НезавершенныеОтложенныеОбработчики, Обработчики)
|
||
|
||
Отбор = Новый Структура;
|
||
Отбор.Вставить("ИмяБиблиотеки", ИмяБиблиотеки);
|
||
НезавершенныеОбработчикиБиблиотеки = НезавершенныеОтложенныеОбработчики.НайтиСтроки(Отбор);
|
||
Для Каждого Обработчик Из НезавершенныеОбработчикиБиблиотеки Цикл
|
||
НайденныйОбработчик = Обработчики.Найти(Обработчик.ИмяОбработчика, "ИмяОбработчика", Истина);
|
||
Если НайденныйОбработчик <> Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ЗначениеЗаполнено(Обработчик.Идентификатор) Тогда
|
||
НайденныйОбработчик = Обработчики.Найти(Обработчик.Идентификатор, "Идентификатор", Истина);
|
||
Если НайденныйОбработчик <> Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
// Проверка, что обработчик не был удален.
|
||
ДополнительныйОтбор = Новый Структура;
|
||
ДополнительныйОтбор.Вставить("РежимВыполнения", "Отложенно");
|
||
ДополнительныйОтбор.Вставить("Процедура", Обработчик.ИмяОбработчика);
|
||
НайденныйОбработчик = ИтерацияОбновления.Обработчики.НайтиСтроки(ДополнительныйОтбор);
|
||
Если НайденныйОбработчик.Количество() = 0 Тогда
|
||
Продолжить;
|
||
Иначе
|
||
НайденныйОбработчик = НайденныйОбработчик[0];
|
||
КонецЕсли;
|
||
|
||
// Необходимо запланировать выполнение незавершенного обработчика.
|
||
СтрокаВерсия = Обработчики.Найти(НайденныйОбработчик.Версия, "Версия");
|
||
Если СтрокаВерсия = Неопределено Тогда
|
||
СтрокаВерсия = Обработчики.Добавить();
|
||
СтрокаВерсия.Версия = НайденныйОбработчик.Версия;
|
||
КонецЕсли;
|
||
|
||
НовыйОбработчик = СтрокаВерсия.Строки.Добавить();
|
||
ЗаполнитьЗначенияСвойств(НовыйОбработчик, НайденныйОбработчик, , "РежимВыполнения");
|
||
НовыйОбработчик.ИмяОбработчика = НайденныйОбработчик.Процедура;
|
||
НовыйОбработчик.РежимВыполнения = "Отложенно";
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ПеренестиОбработчикиИзКонстанты(Приемник, Источник)
|
||
|
||
Для Каждого Обработчик Из Источник Цикл
|
||
НовыйОбработчик = Приемник.Добавить();
|
||
ЗаполнитьЗначенияСвойств(НовыйОбработчик, Обработчик);
|
||
НовыйОбработчик.РежимВыполнения = Перечисления.РежимыВыполненияОбработчиков.Отложенно;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОчередьОбработчиковГруппыОбновления(ГруппаОбновления)
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("ГруппаОбновления", ГруппаОбновления);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ОчередьОтложеннойОбработки КАК Очередь,
|
||
| ОбработчикиОбновления.Идентификатор КАК Идентификатор,
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК Обработчик
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.ГруппаОбновления = &ГруппаОбновления";
|
||
Возврат Запрос.Выполнить().Выгрузить();
|
||
|
||
КонецФункции
|
||
|
||
Функция ЕстьОбработчикиТолькоГлавногоУзла()
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ ПЕРВЫЕ 1
|
||
| ИСТИНА
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.ЗапускатьТолькоВГлавномУзле = ИСТИНА";
|
||
Возврат Запрос.Выполнить().Выгрузить().Количество() > 0;
|
||
|
||
КонецФункции
|
||
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ОбработчикДляВыполнения - Неопределено
|
||
// - СтрокаТаблицыЗначений:
|
||
// ** ИмяОбработчика - Строка.
|
||
// ** Идентификатор - УникальныйИдентификатор.
|
||
// * ЗавершеноУспешно - Булево.
|
||
// * ЕстьВыполняющиеся - Булево.
|
||
// * ЕстьНевыполненные - Булево.
|
||
//
|
||
Функция ОбработчикДляВыполнения(Обработчики, ГруппыОбработчиковИЗависимость, СведенияОбОбновлении)
|
||
|
||
ЗависимостьГруппОбработчиков = СведенияОбОбновлении.ЗависимостьГруппОбработчиков;
|
||
ТекущаяИтерация = СведенияОбОбновлении.ТекущаяИтерацияОбновления;
|
||
|
||
ТекущаяГруппаОбновления = Неопределено;
|
||
ОбработчикДляВыполнения = Неопределено;
|
||
ПропускаемыеГруппы = Новый Массив;
|
||
ЗавершеноУспешно = Истина;
|
||
ЕстьВыполняющиеся = Ложь;
|
||
ЕстьОшибки = Ложь;
|
||
ЕстьНевыполненные = Ложь;
|
||
ПрерватьВыполнение = Ложь;
|
||
ВыполняющийсяМногопоточныйОбработчик = Неопределено;
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
Если Обработчик.ИтерацияЗапуска = ТекущаяИтерация Тогда
|
||
// Обработчик в этой итерации обновления уже запускался.
|
||
ЕстьНевыполненные = Истина;
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ПропускаемыеГруппы.Найти(Обработчик.ГруппаОбновления) <> Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.ГруппаОбновления <> 1
|
||
И ЗависимостьГруппОбработчиков[Обработчик.ГруппаОбновления] = Истина Тогда
|
||
НайденнаяСтрока = ГруппыОбработчиковИЗависимость.Найти(Обработчик.ГруппаОбновления - 1, "ГруппаОбновления");
|
||
Если НайденнаяСтрока <> Неопределено Тогда
|
||
ПропускаемыеГруппы.Добавить(Обработчик.ГруппаОбновления);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Если ТекущаяГруппаОбновления = Неопределено Тогда
|
||
ТекущаяГруппаОбновления = Обработчик.ГруппаОбновления;
|
||
ИначеЕсли ТекущаяГруппаОбновления <> Обработчик.ГруппаОбновления Тогда
|
||
// При переходе к следующей группе обновления делается проверка ошибок по предыдущей группе
|
||
// и наличия многопоточных обработчиков, для которых есть порция обновления.
|
||
Если ВыполняющийсяМногопоточныйОбработчик = Неопределено Тогда
|
||
Если ЕстьОшибки Тогда
|
||
ЗавершеноУспешно = Ложь;
|
||
КонецЕсли;
|
||
Иначе
|
||
ОбработчикДляВыполнения = ВыполняющийсяМногопоточныйОбработчик;
|
||
Прервать;
|
||
КонецЕсли;
|
||
ТекущаяГруппаОбновления = Обработчик.ГруппаОбновления;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.Статус = Перечисления.СтатусыОбработчиковОбновления.Выполняется
|
||
И Не Обработчик.ОбработкаПорцииЗавершена Тогда
|
||
Если Обработчик.Многопоточный Тогда
|
||
Если ЕстьПорцииДляОбновления(Обработчик) Тогда
|
||
ВыполняющийсяМногопоточныйОбработчик = Обработчик;
|
||
КонецЕсли;
|
||
ИначеЕсли ПотокиОбновления().Количество() = 0 Тогда
|
||
ОбработчикДляВыполнения = Обработчик;
|
||
КонецЕсли;
|
||
ЕстьВыполняющиеся = Истина;
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.Статус = Перечисления.СтатусыОбработчиковОбновления.Приостановлен Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
МаксимумПопытокОбновления = МаксимумПопытокОбновления(Обработчик);
|
||
Если Обработчик.ЧислоПопыток >= МаксимумПопытокОбновления Тогда
|
||
Если Обработчик.Статус = Перечисления.СтатусыОбработчиковОбновления.Ошибка Тогда
|
||
ПрерватьВыполнение = Истина;
|
||
Продолжить;
|
||
ИначеЕсли ВсеОбработчикиЗациклились() Тогда
|
||
ОтметитьЗациклившиесяОбработчики();
|
||
ПрерватьВыполнение = Истина;
|
||
Продолжить;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ОбработчикДляВыполнения = Обработчик;
|
||
Прервать;
|
||
КонецЦикла;
|
||
|
||
Если ОбработчикДляВыполнения = Неопределено И ВыполняющийсяМногопоточныйОбработчик <> Неопределено Тогда
|
||
ОбработчикДляВыполнения = ВыполняющийсяМногопоточныйОбработчик;
|
||
КонецЕсли;
|
||
|
||
Если ЕстьОшибки Или ПрерватьВыполнение Тогда
|
||
ЗавершеноУспешно = Ложь;
|
||
КонецЕсли;
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("ОбработчикДляВыполнения", ОбработчикДляВыполнения);
|
||
Результат.Вставить("ЗавершеноУспешно", ЗавершеноУспешно);
|
||
Результат.Вставить("ПрерватьВыполнение", ПрерватьВыполнение);
|
||
Результат.Вставить("ЕстьВыполняющиеся", ЕстьВыполняющиеся);
|
||
Результат.Вставить("ЕстьНевыполненные", ЕстьНевыполненные);
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция ОбработчикОбновления(ИмяОбработчика)
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("ИмяОбработчика", ИмяОбработчика);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.Статус КАК Статус,
|
||
| ОбработчикиОбновления.Версия КАК Версия,
|
||
| ОбработчикиОбновления.ИмяБиблиотеки КАК ИмяБиблиотеки,
|
||
| ОбработчикиОбновления.ДлительностьОбработки КАК ДлительностьОбработки,
|
||
| ОбработчикиОбновления.РежимВыполнения КАК РежимВыполнения,
|
||
| ОбработчикиОбновления.ВерсияРегистрации КАК ВерсияРегистрации,
|
||
| ОбработчикиОбновления.ВерсияПорядок КАК ВерсияПорядок,
|
||
| ОбработчикиОбновления.Идентификатор КАК Идентификатор,
|
||
| ОбработчикиОбновления.ЧислоПопыток КАК ЧислоПопыток,
|
||
| ОбработчикиОбновления.СтатистикаВыполнения КАК СтатистикаВыполнения,
|
||
| ОбработчикиОбновления.ИнформацияОбОшибке КАК ИнформацияОбОшибке,
|
||
| ОбработчикиОбновления.Комментарий КАК Комментарий,
|
||
| ОбработчикиОбновления.Приоритет КАК Приоритет,
|
||
| ОбработчикиОбновления.ПроцедураПроверки КАК ПроцедураПроверки,
|
||
| ОбработчикиОбновления.ПроцедураЗаполненияДанныхОбновления КАК ПроцедураЗаполненияДанныхОбновления,
|
||
| ОбработчикиОбновления.ОчередьОтложеннойОбработки КАК ОчередьОтложеннойОбработки,
|
||
| ОбработчикиОбновления.ЗапускатьТолькоВГлавномУзле КАК ЗапускатьТолькоВГлавномУзле,
|
||
| ОбработчикиОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами КАК ЗапускатьИВПодчиненномУзлеРИБСФильтрами,
|
||
| ОбработчикиОбновления.Многопоточный КАК Многопоточный,
|
||
| ОбработчикиОбновления.ОбработкаПорцииЗавершена КАК ОбработкаПорцииЗавершена,
|
||
| ОбработчикиОбновления.ГруппаОбновления КАК ГруппаОбновления,
|
||
| ОбработчикиОбновления.ИтерацияЗапуска КАК ИтерацияЗапуска,
|
||
| ОбработчикиОбновления.ОбрабатываемыеДанные КАК ОбрабатываемыеДанные,
|
||
| ОбработчикиОбновления.РежимВыполненияОтложенногоОбработчика КАК РежимВыполненияОтложенногоОбработчика
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.ИмяОбработчика = &ИмяОбработчика";
|
||
Результат = Запрос.Выполнить().Выгрузить();
|
||
Если Результат.Количество() = 0 Тогда
|
||
Возврат Неопределено;
|
||
Иначе
|
||
Возврат Результат[0];
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Механизм многопоточного обновления.
|
||
|
||
// Имя группы потоков регистрации данных для отложенного обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - имя группы.
|
||
//
|
||
Функция ГруппаПотоковРегистрацииДанныхОтложенногоОбновления()
|
||
|
||
Возврат "Регистрация";
|
||
|
||
КонецФункции
|
||
|
||
// Имя группы потоков отложенного обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - имя группы.
|
||
//
|
||
Функция ГруппаПотоковОтложенногоОбновления()
|
||
|
||
Возврат "Обновление";
|
||
|
||
КонецФункции
|
||
|
||
// Имя группы потоков поиска порций данных для многопоточного выполнения обработчиков обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - имя группы.
|
||
//
|
||
Функция ГруппаПотоковПоискаПорций()
|
||
|
||
Возврат "Поиск";
|
||
|
||
КонецФункции
|
||
|
||
// Создать новое описание потоков регистрации данных отложенного обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// см. НовоеОписаниеПотоков
|
||
//
|
||
Функция НовоеОписаниеГруппПотоковРегистрацииДанныхОтложенногоОбновления() Экспорт
|
||
|
||
ГруппаРегистрации = НовоеОписаниеГруппыПотоков();
|
||
ГруппаРегистрации.Процедура =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ЗаполнитьДанныеОтложенногоОбработчика";
|
||
ГруппаРегистрации.ПроцедураЗавершения =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ЗавершитьРегистрациюДанныхОтложенногоОбновления";
|
||
|
||
Группы = Новый Соответствие;
|
||
Группы[ГруппаПотоковРегистрацииДанныхОтложенногоОбновления()] = ГруппаРегистрации;
|
||
|
||
Возврат Группы;
|
||
|
||
КонецФункции
|
||
|
||
// Добавить поток регистрации данных отложенного обновления.
|
||
//
|
||
// Параметры:
|
||
// ОписаниеОбрабатываемыхДанных - см. НовоеОписаниеОбрабатываемыхДанных
|
||
//
|
||
// Возвращаемое значение:
|
||
// СтрокаТаблицыЗначений - см. НовоеОписаниеПотоков
|
||
//
|
||
Функция ДобавитьПотокРегистрацииДанныхОтложенногоОбновления(ОписаниеОбрабатываемыхДанных)
|
||
|
||
ШаблонНаименования = НСтр("ru = 'Регистрация данных обработчика обновления ""%1""'");
|
||
ОписаниеОбрабатываемыхДанных.Статус = "Выполняется";
|
||
|
||
Поток = НовыйПоток();
|
||
Поток.ПараметрыПроцедуры = ОписаниеОбрабатываемыхДанных;
|
||
Поток.ПараметрыПроцедурыЗавершения = ОписаниеОбрабатываемыхДанных;
|
||
Поток.Группа = ГруппаПотоковРегистрацииДанныхОтложенногоОбновления();
|
||
Поток.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонНаименования,
|
||
ОписаниеОбрабатываемыхДанных.ИмяОбработчика);
|
||
|
||
СохранитьПотокОбновления(Поток);
|
||
|
||
Возврат Поток;
|
||
|
||
КонецФункции
|
||
|
||
// Завершить регистрацию данных отложенного обновления.
|
||
// Вызывается автоматически в основном потоке, после завершения выполнения ЗаполнитьДанныеОтложенногоОбработчика().
|
||
//
|
||
// Параметры:
|
||
// ОписаниеОбрабатываемыхДанных - см. НовоеОписаниеОбрабатываемыхДанных
|
||
// АдресРезультата - Строка - адрес временного хранилища с результатом из ЗаполнитьДанныеОтложенногоОбработчика().
|
||
//
|
||
Процедура ЗавершитьРегистрациюДанныхОтложенногоОбновления(ОписаниеОбрабатываемыхДанных,
|
||
АдресРезультата) Экспорт
|
||
|
||
Результат = ПолучитьИзВременногоХранилища(АдресРезультата);
|
||
|
||
ЗаполнитьЗначенияСвойств(ОписаниеОбрабатываемыхДанных, Результат);
|
||
ОписаниеОбрабатываемыхДанных.Статус = "Выполнено";
|
||
|
||
Если ЭтоОписаниеДанныхМногопоточногоОбработчика(ОписаниеОбрабатываемыхДанных) Тогда
|
||
ИсправитьПолныеИменаВПараметрахВыборки(ОписаниеОбрабатываемыхДанных.ПараметрыВыборки);
|
||
КонецЕсли;
|
||
|
||
ОбрабатываемыеДанные = Новый ХранилищеЗначения(ОписаниеОбрабатываемыхДанных, Новый СжатиеДанных(9));
|
||
УстановитьСвойствоОбработчика(ОписаниеОбрабатываемыхДанных.ИмяОбработчика, "ОбрабатываемыеДанные", ОбрабатываемыеДанные);
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
Если Результат.ДанныеОбновления <> Неопределено Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.СохранитьДанныеОбновления(Результат.ДанныеОбновления, Результат.ИмяФайлаСИзменениями);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Создать новое описание потоков обработчиков отложенного обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// см. НовоеОписаниеПотоков
|
||
//
|
||
Функция НовоеОписаниеГруппПотоковОбработчиковОтложенногоОбновления() Экспорт
|
||
|
||
ГруппаОбновления = НовоеОписаниеГруппыПотоков();
|
||
ГруппаОбновления.Процедура =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ВыполнитьОтложенныйОбработчик";
|
||
ГруппаОбновления.ПроцедураЗавершения =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ЗавершитьВыполнениеОтложенногоОбработчика";
|
||
ГруппаОбновления.ПриАварийномЗавершении =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ПриАварийномЗавершенииПотокаОтложенногоОбработчика";
|
||
ГруппаОбновления.ПриОтменеПотока =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ПриОтменеПотокаОтложенногоОбработчика";
|
||
|
||
ГруппаПоиска = НовоеОписаниеГруппыПотоков();
|
||
ГруппаПоиска.Процедура =
|
||
"ОбновлениеИнформационнойБазыСлужебный.НайтиПорциюДляОбновления";
|
||
ГруппаПоиска.ПроцедураЗавершения =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ЗавершитьПоискПорцииДляОбновления";
|
||
ГруппаПоиска.ПриАварийномЗавершении =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ПриАварийномЗавершенииПотокаПоискаПорцииДляОбновления";
|
||
ГруппаПоиска.ПриОтменеПотока =
|
||
"ОбновлениеИнформационнойБазыСлужебный.ПриОтменеПотокаПоискаПорцииДляОбновления";
|
||
|
||
Группы = Новый Соответствие;
|
||
Группы[ГруппаПотоковОтложенногоОбновления()] = ГруппаОбновления;
|
||
Группы[ГруппаПотоковПоискаПорций()] = ГруппаПоиска;
|
||
|
||
Возврат Группы;
|
||
|
||
КонецФункции
|
||
|
||
Функция НовыйПоток()
|
||
|
||
Потоки = НовоеОписаниеПотоков();
|
||
Поток = Потоки.Добавить();
|
||
Поток.ИдентификаторПотока = Новый УникальныйИдентификатор;
|
||
|
||
Возврат Поток;
|
||
|
||
КонецФункции
|
||
|
||
// Добавить поток обработчика отложенного обновления.
|
||
//
|
||
// Параметры:
|
||
// ОписаниеПотоков - см. НовоеОписаниеПотоковОбработчиковОтложенногоОбновления
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
// Возвращаемое значение:
|
||
// СтрокаТаблицыЗначений - см. НовоеОписаниеПотоков
|
||
// Булево - Истина, если обработчик не нужно выполнять или Ложь, если выполнение обработчиков нужно завершить.
|
||
//
|
||
Функция ДобавитьПотокОбработчикаОтложенногоОбновления(СведенияОбОбновлении)
|
||
|
||
Поток = Неопределено;
|
||
|
||
Пока Поток = Неопределено Цикл
|
||
КонтекстОбработчика = НовыйКонтекстОбработчика();
|
||
ОбработчикОбновления = НайтиОбработчикОбновления(КонтекстОбработчика);
|
||
|
||
Если ТипЗнч(ОбработчикОбновления) = Тип("СтрокаТаблицыЗначений") Тогда
|
||
Если КонтекстОбработчика.ВыполнитьОбработчик Тогда
|
||
Поток = НовыйПоток();
|
||
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ДополнитьКонтекстМногопоточногоОбработчика(КонтекстОбработчика);
|
||
Добавлен = ДобавитьПотокПоискаДанныхДляОбновления(Поток,
|
||
ОбработчикОбновления,
|
||
КонтекстОбработчика,
|
||
СведенияОбОбновлении);
|
||
|
||
Если Не Добавлен Тогда
|
||
Поток = Истина;
|
||
КонецЕсли;
|
||
Иначе
|
||
ДобавитьПотокОбработчикаОбновления(Поток, КонтекстОбработчика);
|
||
КонецЕсли;
|
||
Иначе
|
||
ЗавершитьВыполнениеОтложенногоОбработчика(КонтекстОбработчика, Неопределено);
|
||
Поток = Неопределено;
|
||
КонецЕсли;
|
||
Иначе
|
||
Поток = ОбработчикОбновления;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат Поток;
|
||
|
||
КонецФункции
|
||
|
||
// Добавить поток поиска данных для обработчика отложенного обновления.
|
||
//
|
||
// Параметры:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// Обработчик - СтрокаДереваЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина, поток добавлен, иначе Ложь.
|
||
//
|
||
Функция ДобавитьПотокПоискаДанныхДляОбновления(Поток, Обработчик, КонтекстОбработчика, СведенияОбОбновлении)
|
||
|
||
ИмяОбработчика = Обработчик.ИмяОбработчика;
|
||
Описание = Обработчик.ОбрабатываемыеДанные.Получить();
|
||
|
||
Если Не Описание.ВыполняетсяПоискПорции Тогда
|
||
ПорцииДляОбновления = Описание.ПорцииДляОбновления;
|
||
|
||
Если Описание.ПоискЗавершен И (ПорцииДляОбновления = Неопределено Или ПорцииДляОбновления.Количество() = 0) Тогда
|
||
ПорцииДляОбновления = Неопределено;
|
||
Описание.ПоследняяВыбраннаяЗапись = Неопределено;
|
||
Описание.ПоискЗавершен = Ложь;
|
||
КонецЕсли;
|
||
|
||
ШаблонНаименования = НСтр("ru = 'Поиск данных для обработчика обновления ""%1""'");
|
||
Поток.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонНаименования, ИмяОбработчика);
|
||
Поток.Группа = ГруппаПотоковПоискаПорций();
|
||
Поток.ПриоритетЗавершения = 1;
|
||
|
||
ПараметрыПоиска = НовыеПараметрыПоискаПорции();
|
||
ПараметрыПоиска.ИмяОбработчика = ИмяОбработчика;
|
||
ПараметрыПоиска.КонтекстОбработчика = КонтекстОбработчика;
|
||
ПараметрыПоиска.ПараметрыВыборки = Описание.ПараметрыВыборки;
|
||
ПараметрыПоиска.Очередь = КонтекстОбработчика.Параметры.Очередь;
|
||
ПараметрыПоиска.ФорсироватьОбновление = ФорсироватьОбновление(СведенияОбОбновлении);
|
||
|
||
НеобработаннаяПорция = ПерваяНеобработаннаяПорция(ПорцииДляОбновления);
|
||
|
||
Если НеобработаннаяПорция <> Неопределено Тогда
|
||
ПараметрыПоиска.ИдентификаторПорции = НеобработаннаяПорция.Идентификатор;
|
||
ПараметрыПоиска.ПерваяЗапись = НеобработаннаяПорция.ПерваяЗапись;
|
||
ПараметрыПоиска.ПоследняяЗапись = НеобработаннаяПорция.ПоследняяЗапись;
|
||
ИначеЕсли Описание.ПоследняяВыбраннаяЗапись <> Неопределено Тогда
|
||
ПараметрыПоиска.ПоследняяВыбраннаяЗапись = Описание.ПоследняяВыбраннаяЗапись;
|
||
КонецЕсли;
|
||
|
||
Поток.ПараметрыПроцедуры = ПараметрыПоиска;
|
||
Поток.ПараметрыПроцедурыЗавершения = ПараметрыПоиска;
|
||
Описание.ВыполняетсяПоискПорции = Истина;
|
||
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
УстановитьСвойствоОбработчика(ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(Описание));
|
||
СохранитьПотокОбновления(Поток);
|
||
ЗафиксироватьТранзакцию();
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
Возврат Истина;
|
||
Иначе
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
// Добавить поток обработчика отложенного обновления.
|
||
//
|
||
// Параметры:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
//
|
||
Процедура ДобавитьПотокОбработчикаОбновления(Поток, КонтекстОбработчика)
|
||
|
||
ИмяОбработчика = КонтекстОбработчика.ИмяОбработчика;
|
||
ШаблонНаименования = НСтр("ru = 'Выполнение обработчика обновления ""%1""'");
|
||
Поток.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонНаименования, ИмяОбработчика);
|
||
Поток.Группа = ГруппаПотоковОтложенногоОбновления();
|
||
Поток.ПараметрыПроцедуры = КонтекстОбработчика;
|
||
Поток.ПараметрыПроцедурыЗавершения = КонтекстОбработчика;
|
||
|
||
СохранитьПотокОбновления(Поток);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Выполнить отложенный обработчик в фоновом задании.
|
||
// Выполняется только, если КонтекстОбработчика.ВыполнитьОбработчик = Истина (т.е. не в подчиненном узле РИБ).
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// АдресРезультата - Строка - адрес временного хранилища для сохранения результата выполнения процедуры.
|
||
//
|
||
Процедура ВыполнитьОтложенныйОбработчик(КонтекстОбработчика, АдресРезультата) Экспорт
|
||
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = КонтекстОбработчика.ПараметрыОбработчикаОбновления;
|
||
|
||
ПодсистемаСуществует = ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом");
|
||
ОтключитьОбновлениеКлючейДоступа(Истина, ПодсистемаСуществует);
|
||
Попытка
|
||
ПараметрыВызова = Новый Массив;
|
||
ПараметрыВызова.Добавить(КонтекстОбработчика.Параметры);
|
||
Результат = НовыйРезультатВыполненияОтложенногоОбработчика();
|
||
|
||
Если КонтекстОбработчика.Параметры.Свойство("ОбновляемыеДанные") Тогда
|
||
ВсегоДанных = 0;
|
||
Для Каждого СтрокаОбновляемыйОбъект Из КонтекстОбработчика.Параметры.ОбновляемыеДанные.НаборДанных Цикл
|
||
ВсегоДанных = ВсегоДанных + СтрокаОбновляемыйОбъект.Данные.Количество();
|
||
КонецЦикла;
|
||
Результат.ПереданоДанныхДляОбработки = ВсегоДанных;
|
||
КонецЕсли;
|
||
Результат.НачалоПроцедурыОбработчика = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(КонтекстОбработчика.ИмяОбработчика, ПараметрыВызова);
|
||
Результат.ЗавершениеПроцедурыОбработчика = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
|
||
Результат.Параметры = КонтекстОбработчика.Параметры;
|
||
Результат.ПараметрыОбработчикаОбновления = ПараметрыСеанса.ПараметрыОбработчикаОбновления;
|
||
|
||
Попытка
|
||
ПроверитьВложеннуюТранзакцию(КонтекстОбработчика.ТранзакцияАктивнаНаНачалоВыполнения,
|
||
КонтекстОбработчика.ИмяОбработчика);
|
||
Исключение
|
||
Результат.ИнформацияОбОшибке = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
|
||
Результат.ЕстьНеЗакрытыеТранзакции = Истина;
|
||
|
||
Пока ТранзакцияАктивна() Цикл
|
||
ОтменитьТранзакцию();
|
||
КонецЦикла;
|
||
КонецПопытки;
|
||
|
||
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
|
||
ОтключитьОбновлениеКлючейДоступа(Ложь, ПодсистемаСуществует);
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(НовыеПараметрыОбработчикаОбновления());
|
||
Исключение
|
||
ОтключитьОбновлениеКлючейДоступа(Ложь, ПодсистемаСуществует);
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(НовыеПараметрыОбработчикаОбновления());
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Завершить выполнение отложенного обработчика.
|
||
// Вызывается автоматически в основном потоке, после завершения выполнения ВыполнитьОтложенныйОбработчик().
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// АдресРезультата - Строка - адрес временного хранилища с результатом из ВыполнитьОтложенныйОбработчик().
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
Процедура ЗавершитьВыполнениеОтложенногоОбработчика(КонтекстОбработчика, АдресРезультата) Экспорт
|
||
|
||
КонтекстОбработчика.Вставить("ПропуститьОтменуТранзакций");
|
||
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
ОбработчикОбновления = ОбработчикОбновления(КонтекстОбработчика.ИмяОбработчика);
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика, "ОбработкаПорцииЗавершена", Истина);
|
||
|
||
ЗагрузитьРезультатВыполненияОбработчика(КонтекстОбработчика, АдресРезультата);
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = КонтекстОбработчика.ПараметрыОбработчикаОбновления;
|
||
|
||
Если КонтекстОбработчика.ЗапускВыполненБезОшибок Тогда
|
||
ПослеЗапускаПроцедурыОбработкиДанных(КонтекстОбработчика, КонтекстОбработчика.ИмяОбработчика);
|
||
КонецЕсли;
|
||
|
||
ЗавершитьПроцедуруОбработкиДанных(КонтекстОбработчика, КонтекстОбработчика.ИмяОбработчика);
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(НовыеПараметрыОбработчикаОбновления());
|
||
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ЗавершитьВыполнениеМногопоточногоОбработчика(КонтекстОбработчика, КонтекстОбработчика.ИмяОбработчика);
|
||
КонецЕсли;
|
||
|
||
ЗавершитьВыполнениеОтложенногоОбработчикаОбновления(КонтекстОбработчика);
|
||
РассчитатьВремяВыполненияПроцедурыОбработчика(КонтекстОбработчика, КонтекстОбработчика.ИмяОбработчика);
|
||
ЗафиксироватьТранзакцию();
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
КонтекстОбработчика.Удалить("ПропуститьОтменуТранзакций");
|
||
|
||
Если КонтекстОбработчика.Свойство("ОшибкаПриЗавершенииОбработчика") Тогда
|
||
ВызватьИсключение КонтекстОбработчика.ОшибкаПриЗавершенииОбработчика;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Рассчитать время выполнения процедуры обработки данных (не всего обработчика).
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// ИмяОбработчика - Строка
|
||
//
|
||
Процедура РассчитатьВремяВыполненияПроцедурыОбработчика(КонтекстОбработчика, ИмяОбработчика)
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(ИмяОбработчика);
|
||
|
||
НачалоПроцедурыОбработчика = ?(КонтекстОбработчика.НачалоПроцедурыОбработчика = Неопределено, 0,
|
||
КонтекстОбработчика.НачалоПроцедурыОбработчика);
|
||
ЗавершениеПроцедурыОбработчика = ?(КонтекстОбработчика.ЗавершениеПроцедурыОбработчика = Неопределено, 0,
|
||
КонтекстОбработчика.ЗавершениеПроцедурыОбработчика);
|
||
ПереданоДанныхДляОбработки = ?(КонтекстОбработчика.ПереданоДанныхДляОбработки = Неопределено, 0,
|
||
КонтекстОбработчика.ПереданоДанныхДляОбработки);
|
||
ДлительностьПроцедурыОбработчика = ЗавершениеПроцедурыОбработчика - НачалоПроцедурыОбработчика;
|
||
НачалоВыполнения = '00010101' + НачалоПроцедурыОбработчика / 1000;
|
||
ЗавершениеВыполнения = '00010101' + ЗавершениеПроцедурыОбработчика / 1000;
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
СтатистикаНачало = СтатистикаВыполнения["НачалоПроцедурыОбработчика"];
|
||
СтатистикаЗавершение = СтатистикаВыполнения["ЗавершениеПроцедурыОбработчика"];
|
||
СтатистикаДанныхДляОбработки = СтатистикаВыполнения["ПереданоДанныхДляОбработки"];
|
||
СтатистикаДлительность = СтатистикаВыполнения["ДлительностьПроцедурыОбработчика"];
|
||
|
||
Если СтатистикаНачало = Неопределено Тогда
|
||
СтатистикаНачало = Новый Массив;
|
||
СтатистикаВыполнения["НачалоПроцедурыОбработчика"] = СтатистикаНачало;
|
||
КонецЕсли;
|
||
|
||
Если СтатистикаЗавершение = Неопределено Тогда
|
||
СтатистикаЗавершение = Новый Массив;
|
||
СтатистикаВыполнения["ЗавершениеПроцедурыОбработчика"] = СтатистикаЗавершение;
|
||
КонецЕсли;
|
||
|
||
Если СтатистикаДанныхДляОбработки = Неопределено Тогда
|
||
СтатистикаДанныхДляОбработки = Новый Массив;
|
||
СтатистикаВыполнения["ПереданоДанныхДляОбработки"] = СтатистикаДанныхДляОбработки;
|
||
КонецЕсли;
|
||
|
||
Если СтатистикаДлительность = Неопределено Тогда
|
||
СтатистикаДлительность = Новый Массив;
|
||
СтатистикаВыполнения["ДлительностьПроцедурыОбработчика"] = СтатистикаДлительность;
|
||
КонецЕсли;
|
||
|
||
СтатистикаНачало.Добавить(НачалоВыполнения);
|
||
СтатистикаЗавершение.Добавить(ЗавершениеВыполнения);
|
||
СтатистикаДанныхДляОбработки.Добавить(ПереданоДанныхДляОбработки);
|
||
СтатистикаДлительность.Добавить(ДлительностьПроцедурыОбработчика);
|
||
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика,
|
||
"СтатистикаВыполнения",
|
||
Новый ХранилищеЗначения(СтатистикаВыполнения));
|
||
|
||
КонецПроцедуры
|
||
|
||
// Обработчик аварийного завершения выполнения потока отложенного обновления.
|
||
//
|
||
// Параметры:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// ИнформацияОбОшибке - ИнформацияОбОшибке - описание возникшей ошибки.
|
||
//
|
||
Процедура ПриАварийномЗавершенииПотокаОтложенногоОбработчика(Поток, ИнформацияОбОшибке) Экспорт
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(Поток.ПараметрыПроцедуры.ИмяОбработчика);
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика, "ОбработкаПорцииЗавершена", Истина);
|
||
ОбработатьИсключениеОбработчика(Поток.ПараметрыПроцедуры, ОбработчикОбновления, ИнформацияОбОшибке);
|
||
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ОтменитьОбработкуДанныхМногопоточногоОбработчика(Поток, ОбработчикОбновления);
|
||
КонецЕсли;
|
||
|
||
КонтекстОбработчика = Поток.ПараметрыПроцедурыЗавершения;
|
||
ЗавершитьВыполнениеОтложенногоОбработчикаОбновления(КонтекстОбработчика);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Обработчик отмены выполнения потока.
|
||
//
|
||
// Параметры:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
//
|
||
Процедура ПриОтменеПотокаОтложенногоОбработчика(Поток) Экспорт
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(Поток.ПараметрыПроцедуры.ИмяОбработчика);
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика, "ОбработкаПорцииЗавершена", Истина);
|
||
|
||
Если ОбработчикОбновления.Статус = Перечисления.СтатусыОбработчиковОбновления.Выполняется Тогда
|
||
УстановитьСтатусОбработчика(ОбработчикОбновления.ИмяОбработчика, "НеВыполнялся");
|
||
КонецЕсли;
|
||
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ОтменитьОбработкуДанныхМногопоточногоОбработчика(Поток, ОбработчикОбновления);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Загрузить результат выполнения обработчика из временного хранилища в контекст обработчика обновления.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// АдресРезультата - Строка - адрес результата во временном хранилище.
|
||
//
|
||
Процедура ЗагрузитьРезультатВыполненияОбработчика(КонтекстОбработчика, АдресРезультата)
|
||
|
||
Если АдресРезультата <> Неопределено Тогда
|
||
Результат = ПолучитьИзВременногоХранилища(АдресРезультата); // см. НовыйРезультатВыполненияОтложенногоОбработчика
|
||
Иначе
|
||
Результат = Неопределено;
|
||
КонецЕсли;
|
||
|
||
Если Результат <> Неопределено Тогда
|
||
Если КонтекстОбработчика.ЗаписыватьВЖурнал Тогда
|
||
КонтекстОбработчика.ДетальноеОписаниеОбработчика.Параметры = Результат.Параметры;
|
||
КонецЕсли;
|
||
|
||
КонтекстОбработчика.ЕстьНеЗакрытыеТранзакции = Результат.ЕстьНеЗакрытыеТранзакции;
|
||
КонтекстОбработчика.ЗавершениеПроцедурыОбработчика = Результат.ЗавершениеПроцедурыОбработчика;
|
||
КонтекстОбработчика.ИнформацияОбОшибке = Результат.ИнформацияОбОшибке;
|
||
КонтекстОбработчика.НачалоПроцедурыОбработчика = Результат.НачалоПроцедурыОбработчика;
|
||
КонтекстОбработчика.ПереданоДанныхДляОбработки = Результат.ПереданоДанныхДляОбработки;
|
||
КонтекстОбработчика.Параметры = Результат.Параметры;
|
||
КонтекстОбработчика.ПараметрыОбработчикаОбновления = Результат.ПараметрыОбработчикаОбновления;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УдалитьВсеПотокиОбновления()
|
||
|
||
НаборЗаписей = РегистрыСведений.ПотокиОбновления.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
// Контекст выполнения обработчика обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - описание контекста (сериализуется для возможности передачи в фоновое задание):
|
||
// * ВыполнитьОбработчик - Булево - если Истина, то обработчик готов к выполнению.
|
||
// * ДетальноеОписаниеОбработчика - см. ПодготовитьДетальнуюИнформациюОХодеОбновления
|
||
// * ЗавершениеПроцедурыОбработчика - Число - завершение процедуры обработки данных.
|
||
// * ЗаписыватьВЖурнал - Булево - см. Константы.ДетализироватьОбновлениеИБВЖурналеРегистрации.
|
||
// * ЗапускВыполненБезОшибок - Булево - если Истина, то при запуске обработчика не возникло исключений.
|
||
// * ИдентификаторОбработчика - УникальныйИдентификатор - идентификатор обработчика обновления.
|
||
// * ИмяОбработчика - Строка - имя обработчика обновления.
|
||
// * ИндексОписанияЦиклаОбновления - Число - индекс элемента плана обновления.
|
||
// * ИндексТекущегоЦиклаОбновления - Число - индекс текущего элемента плана обновления.
|
||
// * НачалоОбработкиДанных - Дата - время начала выполнения обработчика обновления.
|
||
// * НачалоПроцедурыОбработчика - Число - начало процедуры обработки данных.
|
||
// * ПереданоДанныхДляОбработки - Число - количество объектов, переданных для обработки.
|
||
// * ПараллельныйРежим - Булево - признак параллельного режима выполнения обработчика обновления.
|
||
// * Параметры - Структура - параметры обработчика обновления со свойствами:
|
||
// ** ОбновляемыеДанные - см. НоваяПорцияДляОбновления
|
||
// * ПараметрыОбновления - Структура - описание параметров обновления.
|
||
// * ПараметрыОбработчикаОбновления - см. ПараметрыСеанса.ПараметрыОбработчикаОбновления
|
||
// * ПропуститьПроверкуОбработанныхДанных - Булево - пропустить проверку в подчиненном узле РИБ.
|
||
// * ТекущаяИтерацияОбновления - Число - номер текущей итерации обновления.
|
||
// * ТранзакцияАктивнаНаНачалоВыполнения - Булево - состояние активности транзакции перед выполнением обработчика.
|
||
// * ВерсияПодсистемыНаНачалоОбновления - Строка - версия подсистемы, к которой относится обработчик обновления,
|
||
// на момент начала обновления.
|
||
//
|
||
Функция НовыйКонтекстОбработчика()
|
||
|
||
КонтекстОбработчика = Новый Структура;
|
||
|
||
КонтекстОбработчика.Вставить("ВыполнитьОбработчик", Ложь);
|
||
КонтекстОбработчика.Вставить("ДетальноеОписаниеОбработчика");
|
||
КонтекстОбработчика.Вставить("ЕстьНеЗакрытыеТранзакции", Ложь);
|
||
КонтекстОбработчика.Вставить("ЗавершениеПроцедурыОбработчика");
|
||
КонтекстОбработчика.Вставить("ЗаписыватьВЖурнал");
|
||
КонтекстОбработчика.Вставить("ЗапускВыполненБезОшибок", Ложь);
|
||
КонтекстОбработчика.Вставить("ИдентификаторОбработчика");
|
||
КонтекстОбработчика.Вставить("ИмяОбработчика");
|
||
КонтекстОбработчика.Вставить("ИндексОписанияЦиклаОбновления");
|
||
КонтекстОбработчика.Вставить("ИндексТекущегоЦиклаОбновления");
|
||
КонтекстОбработчика.Вставить("ИнформацияОбОшибке");
|
||
КонтекстОбработчика.Вставить("НачалоОбработкиДанных");
|
||
КонтекстОбработчика.Вставить("НачалоПроцедурыОбработчика");
|
||
КонтекстОбработчика.Вставить("ПереданоДанныхДляОбработки");
|
||
КонтекстОбработчика.Вставить("ПараллельныйРежим");
|
||
КонтекстОбработчика.Вставить("Параметры");
|
||
КонтекстОбработчика.Вставить("ПараметрыОбновления");
|
||
КонтекстОбработчика.Вставить("ПараметрыОбработчикаОбновления");
|
||
КонтекстОбработчика.Вставить("ПропуститьПроверкуОбработанныхДанных", Ложь);
|
||
КонтекстОбработчика.Вставить("ТекущаяИтерацияОбновления");
|
||
КонтекстОбработчика.Вставить("ТранзакцияАктивнаНаНачалоВыполнения");
|
||
КонтекстОбработчика.Вставить("ВерсияПодсистемыНаНачалоОбновления");
|
||
|
||
Возврат КонтекстОбработчика;
|
||
|
||
КонецФункции
|
||
|
||
// Дополнить контекст обработчика полями для многопоточного обработчика.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
//
|
||
Процедура ДополнитьКонтекстМногопоточногоОбработчика(КонтекстОбработчика)
|
||
|
||
КонтекстОбработчика.Параметры.Вставить("ОбновляемыеДанные");
|
||
|
||
КонецПроцедуры
|
||
|
||
// Результат выполнения отложенного обработчика обновления для передачи в процедуру завершения
|
||
// его выполнения в управляющем потоке.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ЕстьНеЗакрытыеТранзакции - Булево - признак наличия не закрытых транзакций в самом обработчике.
|
||
// * ЗавершениеПроцедурыОбработчика - Число - время завершения выполнения процедуры обработчика обновления.
|
||
// * ИнформацияОбОшибке - Строка - описание ошибки (если была).
|
||
// * НачалоПроцедурыОбработчика - Число - время начала выполнения процедуры обработчика обновления.
|
||
// * ПереданоДанныхДляОбработки - Число - количество объектов, переданных для обработки.
|
||
// * Параметры - Структура - параметры, переданные в обработчик обновления.
|
||
// * ПараметрыОбработчикаОбновления - ФиксированнаяСтруктура - значение параметра сеанса
|
||
// ПараметрыОбработчикаОбновления.
|
||
//
|
||
Функция НовыйРезультатВыполненияОтложенногоОбработчика()
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("ЕстьНеЗакрытыеТранзакции", Ложь);
|
||
Результат.Вставить("ЗавершениеПроцедурыОбработчика");
|
||
Результат.Вставить("ИнформацияОбОшибке");
|
||
Результат.Вставить("НачалоПроцедурыОбработчика");
|
||
Результат.Вставить("ПереданоДанныхДляОбработки");
|
||
Результат.Вставить("Параметры");
|
||
Результат.Вставить("ПараметрыОбработчикаОбновления");
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// Количество потоков обновления по умолчанию.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - количество потоков равное 1 (для обратной совместимости), если не переопределено в
|
||
// ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек().
|
||
//
|
||
Функция КоличествоПотоковОбновленияИнформационнойБазыПоУмолчанию()
|
||
|
||
Параметры = НастройкиПодсистемы();
|
||
Возврат Параметры.КоличествоПотоковОбновленияИнформационнойБазыПоУмолчанию;
|
||
|
||
КонецФункции
|
||
|
||
// Определить приоритет обновления.
|
||
//
|
||
// Параметры:
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина - приоритет на обработку данных, Ложь - приоритет на работу пользователей.
|
||
//
|
||
Функция ФорсироватьОбновление(СведенияОбОбновлении)
|
||
|
||
Если Не ОбщегоНазначения.РазделениеВключено() Тогда
|
||
ПараметрЗапускаКлиента = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ПараметрЗапуска");
|
||
Если СтрНайти(НРег(ПараметрЗапускаКлиента), НРег("ФорсироватьОтложенноеОбновление")) > 0 Тогда
|
||
Возврат Истина;
|
||
Иначе
|
||
Возврат СведенияОбОбновлении.УправлениеОтложеннымОбновлением.Свойство("ФорсироватьОбновление");
|
||
КонецЕсли;
|
||
Иначе
|
||
Приоритет = Неопределено;
|
||
ИнтеграцияПодсистемБСП.ПриПолученииПриоритетаОбновления(Приоритет);
|
||
|
||
Если Приоритет = "РаботаПользователей" Тогда
|
||
Возврат Ложь;
|
||
ИначеЕсли Приоритет = "ОбработкаДанных" Тогда
|
||
Возврат Истина;
|
||
Иначе
|
||
Возврат СведенияОбОбновлении.УправлениеОтложеннымОбновлением.Свойство("ФорсироватьОбновление");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Механизм работы с потоками.
|
||
|
||
Процедура СохранитьПотокОбновления(Поток)
|
||
|
||
НаборЗаписей = РегистрыСведений.ПотокиОбновления.СоздатьНаборЗаписей();
|
||
Идентификатор = Поток.ИдентификаторПотока;
|
||
Если Не ЗначениеЗаполнено(Идентификатор) Тогда
|
||
Идентификатор = Новый УникальныйИдентификатор;
|
||
КонецЕсли;
|
||
НаборЗаписей.Отбор.ИдентификаторПотока.Установить(Идентификатор);
|
||
НаборЗаписей.Прочитать();
|
||
|
||
Если НаборЗаписей.Количество() = 0 Тогда
|
||
Запись = НаборЗаписей.Добавить();
|
||
Иначе
|
||
Запись = НаборЗаписей[0];
|
||
КонецЕсли;
|
||
|
||
ЗаполнитьЗначенияСвойств(Запись, Поток, , "ИдентификаторПотока,ПараметрыПроцедуры,ПараметрыПроцедурыЗавершения");
|
||
Запись.ИдентификаторПотока = Идентификатор;
|
||
Запись.ПараметрыПроцедуры = Новый ХранилищеЗначения(Поток.ПараметрыПроцедуры);
|
||
Запись.ПараметрыПроцедурыЗавершения = Новый ХранилищеЗначения(Поток.ПараметрыПроцедурыЗавершения);
|
||
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УдалитьПотокОбновления(ИдентификаторПотока)
|
||
|
||
НаборЗаписей = РегистрыСведений.ПотокиОбновления.СоздатьНаборЗаписей();
|
||
НаборЗаписей.Отбор.ИдентификаторПотока.Установить(ИдентификаторПотока);
|
||
НаборЗаписей.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПотокиОбновления()
|
||
|
||
ТаблицаПотоков = НовоеОписаниеПотоков();
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ПотокиОбновления.АдресРезультата КАК АдресРезультата,
|
||
| ПотокиОбновления.Группа КАК Группа,
|
||
| ПотокиОбновления.Наименование КАК Наименование,
|
||
| ПотокиОбновления.ПараметрыПроцедуры КАК ПараметрыПроцедуры,
|
||
| ПотокиОбновления.ПараметрыПроцедурыЗавершения КАК ПараметрыПроцедурыЗавершения,
|
||
| ПотокиОбновления.ПриоритетЗавершения КАК ПриоритетЗавершения,
|
||
| ПотокиОбновления.ИдентификаторЗадания КАК ИдентификаторЗадания,
|
||
| ПотокиОбновления.ИдентификаторПотока КАК ИдентификаторПотока
|
||
|ИЗ
|
||
| РегистрСведений.ПотокиОбновления КАК ПотокиОбновления";
|
||
Результат = Запрос.Выполнить().Выгрузить();
|
||
Для Каждого Поток Из Результат Цикл
|
||
Строка = ТаблицаПотоков.Добавить();
|
||
ЗаполнитьЗначенияСвойств(Строка, Поток, , "ПараметрыПроцедуры,ПараметрыПроцедурыЗавершения");
|
||
Если Не ЗначениеЗаполнено(Строка.АдресРезультата) Тогда
|
||
Строка.АдресРезультата = Неопределено;
|
||
КонецЕсли;
|
||
Строка.ПараметрыПроцедурыЗавершения = Поток.ПараметрыПроцедурыЗавершения.Получить();
|
||
Строка.ПараметрыПроцедуры = Поток.ПараметрыПроцедуры.Получить();
|
||
КонецЦикла;
|
||
Возврат ТаблицаПотоков;
|
||
|
||
КонецФункции
|
||
|
||
// Выполнить указанный поток.
|
||
//
|
||
// Параметры:
|
||
// Группы - Соответствие
|
||
// Поток - СтрокаТаблицыЗначений - описание потока, см. Потоки в НовоеОписаниеПотоков.
|
||
// ИдентификаторФормы - УникальныйИдентификатор - идентификатор формы, если есть.
|
||
//
|
||
Процедура ВыполнитьПоток(Группы, Поток, ИдентификаторФормы = Неопределено)
|
||
|
||
ОписаниеПотока = Группы[Поток.Группа];
|
||
|
||
Если Не ПустаяСтрока(ОписаниеПотока.Процедура) И Поток.ПараметрыПроцедуры <> Неопределено Тогда
|
||
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(ИдентификаторФормы);
|
||
ПараметрыВыполнения.НаименованиеФоновогоЗадания = Поток.Наименование;
|
||
ПараметрыВыполнения.ОжидатьЗавершение = 0;
|
||
|
||
Если ИдентификаторФормы = Неопределено Тогда
|
||
ПараметрыВыполнения.АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено, Новый УникальныйИдентификатор);
|
||
КонецЕсли;
|
||
|
||
РезультатЗапуска = ДлительныеОперации.ВыполнитьВФоне(ОписаниеПотока.Процедура,
|
||
Поток.ПараметрыПроцедуры,
|
||
ПараметрыВыполнения);
|
||
|
||
Поток.АдресРезультата = РезультатЗапуска.АдресРезультата;
|
||
Статус = РезультатЗапуска.Статус;
|
||
|
||
Если Статус = "Выполняется" Тогда
|
||
Поток.ИдентификаторЗадания = РезультатЗапуска.ИдентификаторЗадания;
|
||
ИначеЕсли Статус <> "Выполняется" И Статус <> "Выполнено" Тогда
|
||
ВызватьИсключение РезультатЗапуска.КраткоеПредставлениеОшибки;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
СохранитьПотокОбновления(Поток);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Завершает выполнение потоков, которые завершили выполнение своих фоновых заданий.
|
||
//
|
||
// Параметры:
|
||
// Потоки - см. НовоеОписаниеПотоков
|
||
// Группы - Соответствие
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина, если завершился один или более потоков, иначе - Ложь.
|
||
//
|
||
Функция ЗавершитьПотокиВыполнившиеФЗ(Потоки, Группы)
|
||
|
||
ЕстьЗавершенныеПотоки = Ложь;
|
||
Потоки.Сортировать("ПриоритетЗавершения Убыв");
|
||
Индекс = Потоки.Количество() - 1;
|
||
|
||
Пока Индекс >= 0 Цикл
|
||
Поток = Потоки[Индекс];
|
||
ОписаниеПотока = Группы[Поток.Группа];
|
||
ИдентификаторЗадания = Поток.ИдентификаторЗадания;
|
||
|
||
Если ЗначениеЗаполнено(ИдентификаторЗадания) Тогда
|
||
Попытка
|
||
ЗаданиеВыполнено = ДлительныеОперации.ЗаданиеВыполнено(ИдентификаторЗадания);
|
||
Исключение
|
||
ИнформацияОбОшибке = ИнформацияОбОшибке();
|
||
ЗаданиеВыполнено = Неопределено;
|
||
|
||
Если Не ПустаяСтрока(ОписаниеПотока.ПриАварийномЗавершении) Тогда
|
||
ПараметрыВызова = Новый Массив;
|
||
ПараметрыВызова.Добавить(Поток);
|
||
ПараметрыВызова.Добавить(ИнформацияОбОшибке);
|
||
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(ОписаниеПотока.ПриАварийномЗавершении, ПараметрыВызова);
|
||
Иначе
|
||
ВызватьИсключение;
|
||
КонецЕсли;
|
||
КонецПопытки;
|
||
КонецЕсли;
|
||
|
||
Если Не ЗначениеЗаполнено(ИдентификаторЗадания) Или ЗаданиеВыполнено <> Ложь Тогда
|
||
Выполнять = Не ПустаяСтрока(ОписаниеПотока.ПроцедураЗавершения)
|
||
И Поток.ПараметрыПроцедурыЗавершения <> Неопределено
|
||
И (Не ЗначениеЗаполнено(ИдентификаторЗадания) Или ЗаданиеВыполнено = Истина)
|
||
И Поток.АдресРезультата <> Неопределено;
|
||
|
||
Если Выполнять Тогда
|
||
ПараметрыВызова = Новый Массив;
|
||
ПараметрыВызова.Добавить(Поток.ПараметрыПроцедурыЗавершения);
|
||
ПараметрыВызова.Добавить(Поток.АдресРезультата);
|
||
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(ОписаниеПотока.ПроцедураЗавершения, ПараметрыВызова);
|
||
КонецЕсли;
|
||
|
||
Если Поток.АдресРезультата <> Неопределено Тогда
|
||
УдалитьИзВременногоХранилища(Поток.АдресРезультата);
|
||
КонецЕсли;
|
||
УдалитьПотокОбновления(Поток.ИдентификаторПотока);
|
||
Потоки.Удалить(Поток);
|
||
ЕстьЗавершенныеПотоки = Истина;
|
||
КонецЕсли;
|
||
|
||
Индекс = Индекс - 1;
|
||
КонецЦикла;
|
||
|
||
Возврат ЕстьЗавершенныеПотоки;
|
||
|
||
КонецФункции
|
||
|
||
// Ожидать завершение всех потоков.
|
||
//
|
||
// Параметры:
|
||
// Группы - Соответствие
|
||
//
|
||
Процедура ОжидатьЗавершениеВсехПотоков(Группы)
|
||
|
||
Потоки = ПотокиОбновления();
|
||
|
||
Пока Потоки.Количество() > 0 Цикл
|
||
Если Не ЗавершитьПотокиВыполнившиеФЗ(Потоки, Группы) Тогда
|
||
ОжидатьЗавершениеПотока(Потоки[0]);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Ожидать завершение любого потока.
|
||
//
|
||
// Параметры:
|
||
// Группы - Соответствие
|
||
//
|
||
Процедура ОжидатьЗавершениеЛюбогоПотока(Группы)
|
||
|
||
Потоки = ПотокиОбновления();
|
||
КоличествоПотоков = Потоки.Количество();
|
||
|
||
Пока КоличествоПотоков > 0 И Потоки.Количество() >= КоличествоПотоков Цикл
|
||
Если Не ЗавершитьПотокиВыполнившиеФЗ(Потоки, Группы) Тогда
|
||
ОжидатьЗавершениеПотока(Потоки[0]);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Ожидать, пока количество выполняющихся потоков не станет меньше максимального.
|
||
//
|
||
// Параметры:
|
||
// Группы - Соответствие
|
||
//
|
||
Процедура ОжидатьСвободныйПоток(Группы)
|
||
|
||
МаксимумПотоков = КоличествоПотоковОбновленияИнформационнойБазы();
|
||
|
||
Потоки = ПотокиОбновления();
|
||
|
||
Пока Потоки.Количество() >= МаксимумПотоков Цикл
|
||
Если ЗавершитьПотокиВыполнившиеФЗ(Потоки, Группы) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ОжидатьЗавершениеПотока(Потоки[0]);
|
||
МаксимумПотоков = КоличествоПотоковОбновленияИнформационнойБазы();
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Отменить выполнение потоков, если они активны.
|
||
//
|
||
// Параметры:
|
||
// Группы - Соответствие
|
||
//
|
||
Процедура ОтменитьВыполнениеВсехПотоков(Группы) Экспорт
|
||
|
||
Потоки = ПотокиОбновления();
|
||
Для Каждого Поток Из Потоки Цикл
|
||
ОписаниеПотока = Группы[Поток.Группа];
|
||
|
||
Если ЗначениеЗаполнено(Поток.ИдентификаторЗадания) Тогда
|
||
ДлительныеОперации.ОтменитьВыполнениеЗадания(Поток.ИдентификаторЗадания);
|
||
КонецЕсли;
|
||
|
||
Если ОписаниеПотока.ПриОтменеПотока <> Неопределено Тогда
|
||
ПараметрыВызова = Новый Массив;
|
||
ПараметрыВызова.Добавить(Поток);
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(ОписаниеПотока.ПриОтменеПотока, ПараметрыВызова);
|
||
КонецЕсли;
|
||
|
||
УдалитьПотокОбновления(Поток.ИдентификаторПотока);
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Описание группы потоков.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - общее описание потоков со следующими полями:
|
||
// * Процедура - Строка - имя процедуры, выполняемой в фоновом задании. Объявление:
|
||
// ИмяПроцедуры(ОписаниеПроцедуры, АдресРезультата), где:
|
||
// ОписаниеПроцедуры - Структура - описание процедуры заполнения.
|
||
// АдресРезультата - Строка - адрес временного хранилища для сохранения результата выполнения.
|
||
// * ПроцедураЗавершения - Строка - имя процедуры, выполняемой, после завершения работы фонового задания. Объявление:
|
||
// ПроцедураЗавершения(ОписаниеПроцедуры, АдресРезультата, ДополнительныеПараметры), где:
|
||
// ОписаниеПроцедуры - Структура - описание процедуры заполнения.
|
||
// АдресРезультата - Строка - адрес временного хранилища с результатом выполнения.
|
||
// ДополнительныеПараметры - Произвольный - дополнительный параметр.
|
||
// * ПриАварийномЗавершении - Строка - обработчик аварийного завершения потока. Объявление:
|
||
// ПриАварийномЗавершении(Поток, ИнформацияОбОшибке, ДополнительныеПараметры), где:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// ИнформацияОбОшибке - ИнформацияОбОшибке - описание возникшей ошибки.
|
||
// ДополнительныеПараметры - Произвольный - дополнительный параметр.
|
||
// * ПриОтменеПотока - Строка - обработчик отмены потока. Объявление:
|
||
// ПриОтменеПотока(Поток, ДополнительныеПараметры), где:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// ДополнительныеПараметры - Произвольный - дополнительный параметр.
|
||
//
|
||
Функция НовоеОписаниеГруппыПотоков()
|
||
|
||
Описание = Новый Структура;
|
||
Описание.Вставить("Процедура");
|
||
Описание.Вставить("ПроцедураЗавершения");
|
||
Описание.Вставить("ПриАварийномЗавершении");
|
||
Описание.Вставить("ПриОтменеПотока");
|
||
|
||
Возврат Описание;
|
||
|
||
КонецФункции
|
||
|
||
// Описание группы потоков.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * Группы - Соответствие из КлючИЗначение - описание групп потоков, где:
|
||
// ** Ключ - Строка - имя группы.
|
||
// ** Значение - см. НовоеОписаниеГруппыПотоков
|
||
// * Потоки - ТаблицаЗначений - описание потоков со следующими колонками:
|
||
// ** Наименование - Строка - произвольное наименование потока (используется в наименовании фонового задания).
|
||
// ** Группа - Строка - имя группы с описанием потока.
|
||
// ** ИдентификаторЗадания - УникальныйИдентификатор - уникальный идентификатор фонового задания.
|
||
// ** ПараметрыПроцедуры - Произвольный - параметры для Процедура.
|
||
// ** ПараметрыПроцедурыЗавершения - Произвольный - параметры для ПроцедураЗавершения.
|
||
// ** АдресРезультата - Строка - адрес временного хранилища для сохранения результата выполнения фонового задания.
|
||
//
|
||
Функция НовоеОписаниеПотоков()
|
||
|
||
Потоки = Новый ТаблицаЗначений;
|
||
Колонки = Потоки.Колонки;
|
||
Колонки.Добавить("Наименование");
|
||
Колонки.Добавить("Группа");
|
||
Колонки.Добавить("ПриоритетЗавершения", Новый ОписаниеТипов("Число"));
|
||
Колонки.Добавить("ИдентификаторЗадания");
|
||
Колонки.Добавить("ИдентификаторПотока");
|
||
Колонки.Добавить("ПараметрыПроцедуры");
|
||
Колонки.Добавить("ПараметрыПроцедурыЗавершения");
|
||
Колонки.Добавить("АдресРезультата");
|
||
|
||
Возврат Потоки;
|
||
|
||
КонецФункции
|
||
|
||
// Ожидать завершение потока в течение указанной длительности.
|
||
//
|
||
// Параметры:
|
||
// Поток - СтрокаТаблицыЗначений - поток, завершение которого необходимо ожидать.
|
||
// Длительность - Число - максимальная длительность ожидания в секундах.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина - поток выполнен, Ложь - поток еще выполняется.
|
||
//
|
||
Функция ОжидатьЗавершениеПотока(Поток, Длительность = 1)
|
||
|
||
Если ЗначениеЗаполнено(Поток.ИдентификаторЗадания) Тогда
|
||
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Поток.ИдентификаторЗадания);
|
||
|
||
Если Задание <> Неопределено Тогда
|
||
Задание = Задание.ОжидатьЗавершенияВыполнения(Длительность);
|
||
ЗаданиеЗавершено = (Задание.Состояние <> СостояниеФоновогоЗадания.Активно);
|
||
Возврат ЗаданиеЗавершено;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Механизм многопоточного выполнения обработчика обновления.
|
||
|
||
// Найти порцию данных для потока обработчика обновления.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыПоиска - см. НовыеПараметрыПоискаПорции
|
||
// АдресРезультата - Строка - адрес результата выполнения процедуры. Возвращается таблица значений.
|
||
//
|
||
Процедура НайтиПорциюДляОбновления(ПараметрыПоиска, АдресРезультата) Экспорт
|
||
|
||
ПараметрыВыборки = ПараметрыПоиска.ПараметрыВыборки;
|
||
ПроверитьПараметрыВыборки(ПараметрыВыборки);
|
||
ПараметрыВыборки.МаксимумВыборки = ОбновлениеИнформационнойБазы.МаксимальноеКоличествоЗаписейВВыборке();
|
||
ПоляУпорядочивания = ПоляУпорядочиванияПриПоискеПорций(ПараметрыПоиска);
|
||
ПараметрыВыборки.ПоляУпорядочивания = ПоляУпорядочивания;
|
||
ПараметрыВыборки.ОптимизироватьВыборкуПоСтраницам = Не ЕстьУпорядочиваниеПоВнешнимТаблицам(ПоляУпорядочивания);
|
||
Максимум = ОбновлениеИнформационнойБазы.МаксимальноеКоличествоЗаписейВВыборке();
|
||
ПараметрыОбхода = ПараметрыОбходаДанныхДляОбновления(ПараметрыПоиска);
|
||
ИтераторОбхода = ТекущиеПараметрыОбхода(ПараметрыОбхода);
|
||
РезультатПоиска = НовыйРезультатПоискаПорции();
|
||
НаборДанных = НовыйНаборДанныхДляОбновления();
|
||
РезультатПоиска.НаборДанных = НаборДанных;
|
||
ПараметрыВыборки = ПараметрыПоиска.ПараметрыВыборки;
|
||
ДополнительныеИсточникиДанных = ПараметрыВыборки.ДополнительныеИсточникиДанных;
|
||
Очередь = ПараметрыПоиска.Очередь;
|
||
|
||
Пока ИтераторОбхода <> Неопределено Цикл
|
||
СсылочныйОбъект = ИтераторОбхода.СсылочныйОбъект;
|
||
ТабличныйОбъект = ИтераторОбхода.ТабличныйОбъект;
|
||
УстановитьГраницуНачалаВыборки(ПараметрыПоиска, ИтераторОбхода.СсылочныйИндекс, ИтераторОбхода.ТабличныйИндекс);
|
||
УстановитьГраницуКонцаВыборки(ПараметрыПоиска, СсылочныйОбъект, ТабличныйОбъект);
|
||
МаксимумВыборки = ПараметрыВыборки.МаксимумВыборки;
|
||
ПараметрыВыборки.ДополнительныеИсточникиДанных = ОбновлениеИнформационнойБазы.ИсточникиДанных(
|
||
ДополнительныеИсточникиДанных,
|
||
СсылочныйОбъект,
|
||
ТабличныйОбъект);
|
||
Данные = ВыбратьДанныеПорции(ПараметрыВыборки, Очередь, СсылочныйОбъект, ТабличныйОбъект);
|
||
Количество = Данные.Количество();
|
||
РезультатПоиска.Количество = РезультатПоиска.Количество + Количество;
|
||
ПараметрыВыборки.МаксимумВыборки = ПараметрыВыборки.МаксимумВыборки - Количество;
|
||
|
||
Если Количество > 0 Тогда
|
||
ЗаписьНабора = НаборДанных.Добавить();
|
||
ЗаписьНабора.СсылочныйОбъект = СсылочныйОбъект;
|
||
ЗаписьНабора.ТабличныйОбъект = ТабличныйОбъект;
|
||
ЗаписьНабора.Данные = Данные;
|
||
КонецЕсли;
|
||
|
||
Если РезультатПоиска.Количество < Максимум Тогда
|
||
СледующиеПараметрыОбхода(ПараметрыОбхода, Количество = МаксимумВыборки);
|
||
ИтераторОбхода = ТекущиеПараметрыОбхода(ПараметрыОбхода);
|
||
Иначе
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
ПараметрыВыборки.ДополнительныеИсточникиДанных = ДополнительныеИсточникиДанных;
|
||
РезультатПоиска.ПоискЗавершен = (ИтераторОбхода = Неопределено);
|
||
ПоместитьВоВременноеХранилище(РезультатПоиска, АдресРезультата);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Проверить корректность заполнения параметров выборки данных обработчика обновления.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыВыборки - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки
|
||
//
|
||
Процедура ПроверитьПараметрыВыборки(ПараметрыВыборки)
|
||
|
||
СпособВыборки = ПараметрыВыборки.СпособВыборки;
|
||
ИзвестныйСпособ = (СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиИзмеренияНезависимогоРегистраСведений())
|
||
Или (СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиРегистраторыРегистра())
|
||
Или (СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиСсылки());
|
||
Если Не ИзвестныйСпособ Тогда
|
||
ШаблонСообщения = НСтр(
|
||
"ru = 'Укажите способ выборки в процедуре регистрации данных к обновлению.
|
||
|Указывается в ""%1"".
|
||
|Сейчас указан неизвестный способ выборки ""%2"".'");
|
||
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонСообщения, СпособВыборки, "Параметры.ПараметрыВыборки.СпособВыборки");
|
||
КонецЕсли;
|
||
|
||
ТаблицыУказаны = Не ПустаяСтрока(ПараметрыВыборки.ПолныеИменаОбъектов)
|
||
Или Не ПустаяСтрока(ПараметрыВыборки.ПолныеИменаРегистров);
|
||
Если Не ТаблицыУказаны Тогда
|
||
ШаблонСообщения = НСтр(
|
||
"ru = 'Укажите обрабатываемые таблицы в процедуре регистрации данных к обновлению.
|
||
|Указывается в ""%1"" и/или
|
||
|""%2"".'");
|
||
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонСообщения,
|
||
"Параметры.ПараметрыВыборки.ПолныеИменаОбъектов", "Параметры.ПараметрыВыборки.ПолныеИменаРегистров");
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Установить границу начала выборки порции.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыПоиска - см. НовыеПараметрыПоискаПорции
|
||
// СсылочныйИндекс - Число - номер итерации по ссылочным объектам.
|
||
// ТабличныйИндекс - Число - номер итерации по табличным объектам.
|
||
//
|
||
Процедура УстановитьГраницуНачалаВыборки(ПараметрыПоиска, СсылочныйИндекс, ТабличныйИндекс)
|
||
|
||
ПараметрыВыборки = ПараметрыПоиска.ПараметрыВыборки;
|
||
ПоследняяВыбраннаяЗапись = ПараметрыПоиска.ПоследняяВыбраннаяЗапись;
|
||
ПерваяЗапись = ПараметрыПоиска.ПерваяЗапись;
|
||
|
||
Если СсылочныйИндекс = 0 И ТабличныйИндекс = 0 Тогда // Выбирается первая страница в цикле выборки.
|
||
ПараметрыВыборки.ПоследняяВыбраннаяЗапись = ПоследняяВыбраннаяЗапись;
|
||
ПараметрыВыборки.ПерваяЗапись = ПерваяЗапись;
|
||
Иначе // Выбираются последующие страницы в цикле выборки (всегда в новом объекте, поэтому сначала).
|
||
ПараметрыВыборки.ПоследняяВыбраннаяЗапись = Неопределено;
|
||
ПараметрыВыборки.ПерваяЗапись = Неопределено;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Установить границу конца выборки порции.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыПоиска - см. НовыеПараметрыПоискаПорции
|
||
// СсылочныйОбъект - Строка - полное имя ссылочного объекта метаданных.
|
||
// ТабличныйОбъект - Строка - полное имя табличного объекта метаданных.
|
||
//
|
||
Процедура УстановитьГраницуКонцаВыборки(ПараметрыПоиска, СсылочныйОбъект, ТабличныйОбъект)
|
||
|
||
ПараметрыВыборки = ПараметрыПоиска.ПараметрыВыборки;
|
||
ПоследняяЗапись = ПараметрыПоиска.ПоследняяЗапись;
|
||
ЭтоПоследнийОбъект = ПоследняяЗапись <> Неопределено
|
||
И СсылочныйОбъект = ПоследняяЗапись[0].Значение
|
||
И ТабличныйОбъект = ПоследняяЗапись[1].Значение;
|
||
|
||
Если ЭтоПоследнийОбъект Тогда // Последний объект в цикле обхода метаданных (конец выборки).
|
||
ПараметрыВыборки.ПоследняяЗапись = ПоследняяЗапись;
|
||
Иначе // Промежуточная выборка.
|
||
ПараметрыВыборки.ПоследняяЗапись = Неопределено;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Выбрать данные порции указанным способом.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыВыборки - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки
|
||
// Очередь - Число - номер очереди.
|
||
// СсылочныйОбъект - Строка - полное имя ссылочного объекта метаданных.
|
||
// ТабличныйОбъект - Строка - полное имя табличного объекта метаданных.
|
||
//
|
||
// Возвращаемое значение:
|
||
// ТаблицаЗначений - данные порции.
|
||
//
|
||
Функция ВыбратьДанныеПорции(ПараметрыВыборки, Очередь, СсылочныйОбъект, ТабличныйОбъект)
|
||
|
||
СпособВыборки = ПараметрыВыборки.СпособВыборки;
|
||
|
||
Если СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиИзмеренияНезависимогоРегистраСведений() Тогда
|
||
Данные = ОбновлениеИнформационнойБазы.ВыбратьИзмеренияНезависимогоРегистраСведенийДляОбработки(
|
||
Очередь,
|
||
ТабличныйОбъект,
|
||
ПараметрыВыборки);
|
||
ИначеЕсли СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиРегистраторыРегистра() Тогда
|
||
Данные = ОбновлениеИнформационнойБазы.ВыбратьРегистраторыРегистраДляОбработки(
|
||
Очередь,
|
||
?(ПустаяСтрока(СсылочныйОбъект), Неопределено, СсылочныйОбъект),
|
||
ТабличныйОбъект,
|
||
ПараметрыВыборки);
|
||
ИначеЕсли СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиСсылки() Тогда
|
||
Данные = ОбновлениеИнформационнойБазы.ВыбратьСсылкиДляОбработки(
|
||
Очередь,
|
||
СсылочныйОбъект,
|
||
ПараметрыВыборки);
|
||
КонецЕсли;
|
||
|
||
Возврат Данные;
|
||
|
||
КонецФункции
|
||
|
||
// Подготовить параметры обхода данных для обновления.
|
||
// По сути найти границу начала выборки (то место, где остановились в последний раз).
|
||
//
|
||
// Параметры:
|
||
// ПараметрыПоиска - см. НовыеПараметрыПоискаПорции
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - параметры поиска, со следующими полями:
|
||
// СсылочныеОбъекты - Массив - имена ссылочных объектов метаданных.
|
||
// ТабличныеОбъектыВсе - Массив - имена табличных объектов метаданных.
|
||
// ТабличныеОбъектыНачало - Массив - имена табличных объектов метаданных на первой итерации.
|
||
//
|
||
Функция ПараметрыОбходаДанныхДляОбновления(ПараметрыПоиска)
|
||
|
||
ПоследняяВыбраннаяЗапись = ПараметрыПоиска.ПоследняяВыбраннаяЗапись;
|
||
ПерваяЗапись = ПараметрыПоиска.ПерваяЗапись;
|
||
ПараметрыВыборки = ПараметрыПоиска.ПараметрыВыборки;
|
||
ПолныеИменаОбъектов = ПараметрыВыборки.ПолныеИменаОбъектов;
|
||
ПолныеИменаРегистров = ПараметрыВыборки.ПолныеИменаРегистров;
|
||
ПолныеИменаРегистровНачало = ПолныеИменаРегистров;
|
||
|
||
Если ПоследняяВыбраннаяЗапись <> Неопределено Тогда // Продолжение выборки по страницам.
|
||
ПерваяСсылочная = ПоследняяВыбраннаяЗапись[0].Значение;
|
||
ПерваяТабличная = ПоследняяВыбраннаяЗапись[1].Значение;
|
||
ИначеЕсли ПерваяЗапись <> Неопределено Тогда // Повтор выборки (завершившейся аварийно).
|
||
ПерваяСсылочная = ПерваяЗапись[0].Значение;
|
||
ПерваяТабличная = ПерваяЗапись[1].Значение;
|
||
Иначе // Начало выборки (выборка первой страницы).
|
||
ПерваяСсылочная = Неопределено;
|
||
ПерваяТабличная = Неопределено;
|
||
КонецЕсли;
|
||
|
||
Если Не ПустаяСтрока(ПолныеИменаОбъектов) И Не ПустаяСтрока(ПерваяСсылочная) Тогда // Есть ссылочные объекты.
|
||
// Установить ссылочную часть начала выборки на место, на котором она остановилась в последний раз.
|
||
ПолныеИменаОбъектовМассив = ОстатокМассива(ПолныеИменаОбъектов, ПерваяСсылочная);
|
||
Иначе
|
||
ПолныеИменаОбъектовМассив = СтрРазделитьСокрЛП(ПолныеИменаОбъектов, ",");
|
||
КонецЕсли;
|
||
|
||
Если Не ПустаяСтрока(ПолныеИменаРегистровНачало) И Не ПустаяСтрока(ПерваяТабличная) Тогда // Есть табличные объекты.
|
||
// Установить табличную часть начала выборки на место, на котором она остановилась в последний раз.
|
||
ПолныеИменаРегистровНачалоМассив = ОстатокМассива(ПолныеИменаРегистровНачало, ПерваяТабличная);
|
||
Иначе
|
||
ПолныеИменаРегистровНачалоМассив = СтрРазделитьСокрЛП(ПолныеИменаРегистровНачало, ",");
|
||
КонецЕсли;
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("СсылочныеОбъекты", ПолныеИменаОбъектовМассив);
|
||
Результат.Вставить("ТабличныеОбъектыВсе", СтрРазделитьСокрЛП(ПолныеИменаРегистров, ","));
|
||
Результат.Вставить("ТабличныеОбъектыНачало", ПолныеИменаРегистровНачалоМассив);
|
||
Результат.Вставить("СсылочныйИндекс", 0);
|
||
Результат.Вставить("ТабличныйИндекс", 0);
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
// Получить следующую порцию параметров обхода данных для обновления.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыОбхода - см. ПараметрыОбходаДанныхДляОбновления
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - параметры обхода текущей итерации в виде структуры со следующими полями:
|
||
// * СсылочныйОбъект - Строка - имя ссылочного объекта.
|
||
// * ТабличныйОбъект - Строка - имя табличного объекта.
|
||
// Неопределено - если обход закончен.
|
||
//
|
||
Функция ТекущиеПараметрыОбхода(ПараметрыОбхода)
|
||
|
||
Если ПараметрыОбхода.СсылочныйИндекс < ПараметрыОбхода.СсылочныеОбъекты.Количество() Тогда
|
||
Если ПараметрыОбхода.СсылочныйИндекс = 0 Тогда
|
||
ТабличныеОбъекты = ПараметрыОбхода.ТабличныеОбъектыНачало;
|
||
Иначе
|
||
ТабличныеОбъекты = ПараметрыОбхода.ТабличныеОбъектыВсе;
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыОбхода.ТабличныйИндекс < ТабличныеОбъекты.Количество() Тогда
|
||
СсылочныйОбъект = ПараметрыОбхода.СсылочныеОбъекты[ПараметрыОбхода.СсылочныйИндекс];
|
||
ТабличныйОбъект = ТабличныеОбъекты[ПараметрыОбхода.ТабличныйИндекс];
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("СсылочныйОбъект", СсылочныйОбъект);
|
||
Результат.Вставить("ТабличныйОбъект", ТабличныйОбъект);
|
||
Результат.Вставить("СсылочныйИндекс", ПараметрыОбхода.СсылочныйИндекс);
|
||
Результат.Вставить("ТабличныйИндекс", ПараметрыОбхода.ТабличныйИндекс);
|
||
|
||
Возврат Результат;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Неопределено;
|
||
|
||
КонецФункции
|
||
|
||
// Перейти к следующим параметрам выборки, если не было выбрано ни одной записи с текущими параметрами.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыОбхода - см. ПараметрыОбходаДанныхДляОбновления
|
||
// ПолнаяВыборка - Булево - Истина, если выбрано максимум записей.
|
||
//
|
||
Процедура СледующиеПараметрыОбхода(ПараметрыОбхода, ПолнаяВыборка)
|
||
|
||
Если Не ПолнаяВыборка Тогда
|
||
Если ПараметрыОбхода.СсылочныйИндекс = 0 Тогда
|
||
ТабличныеОбъекты = ПараметрыОбхода.ТабличныеОбъектыНачало;
|
||
Иначе
|
||
ТабличныеОбъекты = ПараметрыОбхода.ТабличныеОбъектыВсе;
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыОбхода.ТабличныйИндекс = ТабличныеОбъекты.ВГраница() Тогда
|
||
ПараметрыОбхода.ТабличныйИндекс = 0;
|
||
ПараметрыОбхода.СсылочныйИндекс = ПараметрыОбхода.СсылочныйИндекс + 1;
|
||
Иначе
|
||
ПараметрыОбхода.ТабличныйИндекс = ПараметрыОбхода.ТабличныйИндекс + 1;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Получить поля упорядочивания для заданных параметров поиска порции.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыПоиска - см. НовыеПараметрыПоискаПорции
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - Массив - поля упорядочивания.
|
||
//
|
||
Функция ПоляУпорядочиванияПриПоискеПорций(ПараметрыПоиска)
|
||
|
||
ПараметрыВыборки = ПараметрыПоиска.ПараметрыВыборки;
|
||
Возврат ?(ПараметрыПоиска.ФорсироватьОбновление,
|
||
ПараметрыВыборки.ПоляУпорядочиванияПриОбработкеДанных,
|
||
ПараметрыВыборки.ПоляУпорядочиванияПриРаботеПользователей);
|
||
|
||
КонецФункции
|
||
|
||
// Определить, есть ли упорядочивание по полям присоединяемых таблиц.
|
||
//
|
||
// Параметры:
|
||
// ПоляУпорядочивания - Массив - поля упорядочивания.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина, если есть упорядочивание по полям присоединяемых таблиц.
|
||
//
|
||
Функция ЕстьУпорядочиваниеПоВнешнимТаблицам(ПоляУпорядочивания)
|
||
|
||
Для каждого ПолеУпорядочивания Из ПоляУпорядочивания Цикл
|
||
Если СтрНайти(ПолеУпорядочивания, ".") > 0 Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат Ложь;
|
||
|
||
КонецФункции
|
||
|
||
// Получить результат поиска, разбить его на порции и запустить потоки обновления.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыПоиска - см. НовыеПараметрыПоискаПорции
|
||
// АдресРезультата - Строка - адрес результата выполнения НайтиПорциюДляОбновления
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
Процедура ЗавершитьПоискПорцииДляОбновления(ПараметрыПоиска, АдресРезультата) Экспорт
|
||
|
||
РезультатПоиска = ПолучитьИзВременногоХранилища(АдресРезультата);
|
||
Группы = НовоеОписаниеГруппПотоковОбработчиковОтложенногоОбновления();
|
||
КонтекстОбработчика = ПараметрыПоиска.КонтекстОбработчика;
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(КонтекстОбработчика.ИмяОбработчика);
|
||
ОписаниеПроцедурыЗаполнения = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
ПорцииДляОбновления = ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления; // см. НоваяТаблицаПорцийДляОбновления
|
||
ИдентификаторПорции = ПараметрыПоиска.ИдентификаторПорции;
|
||
ЕстьИдентификатор = ИдентификаторПорции <> Неопределено;
|
||
СтараяПорция = ?(ЕстьИдентификатор, ПорцииДляОбновления.Найти(ИдентификаторПорции, "Идентификатор"), Неопределено);
|
||
ЭтоПервыйПоиск = ПараметрыПоиска.ПоследняяВыбраннаяЗапись = Неопределено
|
||
И ПараметрыПоиска.ПерваяЗапись = Неопределено
|
||
И ПараметрыПоиска.ПоследняяЗапись = Неопределено;
|
||
ЭтоПовторныйПоиск = ПараметрыПоиска.ПерваяЗапись <> Неопределено
|
||
И ПараметрыПоиска.ПоследняяЗапись <> Неопределено;
|
||
|
||
Если ЭтоПервыйПоиск Тогда
|
||
СохранитьРезультатПервогоПоиска(РезультатПоиска, ОписаниеПроцедурыЗаполнения);
|
||
ПорцииДляОбновления = ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления;
|
||
ИначеЕсли ЭтоПовторныйПоиск Тогда
|
||
СохранитьРезультатПовторногоПоиска(РезультатПоиска, ОписаниеПроцедурыЗаполнения, ИдентификаторПорции);
|
||
Иначе
|
||
СохранитьРезультатПоиска(РезультатПоиска, ОписаниеПроцедурыЗаполнения);
|
||
КонецЕсли;
|
||
|
||
Если РезультатПоиска.Количество > 0 Тогда
|
||
МаксимумПотоков = КоличествоПотоковОбновленияИнформационнойБазы();
|
||
ПотокиОбновления = ПотокиОбновления();
|
||
СвободныхПотоков = МаксимумПотоков - ПотокиОбновления.Количество() + 1;
|
||
Если СвободныхПотоков = 0 Тогда
|
||
СвободныхПотоков = 1;
|
||
КонецЕсли;
|
||
Фрагменты = РазбитьРезультатПоискаНаФрагменты(РезультатПоиска, СвободныхПотоков);
|
||
КоличествоФрагментов = Фрагменты.Количество();
|
||
|
||
Для НомерФрагмента = 0 По КоличествоФрагментов - 1 Цикл
|
||
Фрагмент = Фрагменты[НомерФрагмента];
|
||
ЕстьСтараяПорция = (НомерФрагмента = 0 И СтараяПорция <> Неопределено);
|
||
|
||
Если ЕстьСтараяПорция Тогда
|
||
Порция = СтараяПорция;
|
||
Фрагмент.Идентификатор = Порция.Идентификатор;
|
||
Иначе
|
||
Порция = ПорцииДляОбновления.Добавить();
|
||
Порция.Идентификатор = Фрагмент.Идентификатор;
|
||
КонецЕсли;
|
||
|
||
Порция.ПерваяЗапись = Фрагмент.ПерваяЗапись;
|
||
Порция.ПоследняяЗапись = Фрагмент.ПоследняяЗапись;
|
||
Порция.Обрабатывается = Истина;
|
||
|
||
// Если порций больше одной, то для каждой свой КлючЗаписиПрогрессаОбновления прогресса обновления
|
||
ПараметрыОбработчикаОбновления = Новый Структура(КонтекстОбработчика.ПараметрыОбработчикаОбновления);
|
||
ПараметрыОбработчикаОбновления.КлючЗаписиПрогрессаОбновления = Новый УникальныйИдентификатор;
|
||
КонтекстОбработчика.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(ПараметрыОбработчикаОбновления);
|
||
ОбработатьФрагментДанныхВПотоке(Фрагмент, Группы, КонтекстОбработчика);
|
||
КонецЦикла;
|
||
Иначе
|
||
Фрагмент = НоваяПорцияДляОбновления();
|
||
Фрагмент.НаборДанных = НовыйНаборДанныхДляОбновления();
|
||
ОбработатьФрагментДанныхВПотоке(Фрагмент, Группы, КонтекстОбработчика);
|
||
КонецЕсли;
|
||
|
||
ОписаниеПроцедурыЗаполнения.ВыполняетсяПоискПорции = Ложь;
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(ОписаниеПроцедурыЗаполнения));
|
||
|
||
КонецПроцедуры
|
||
|
||
// Обработчик аварийного завершения выполнения потока поиска порции для обновления.
|
||
//
|
||
// Параметры:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// ИнформацияОбОшибке - ИнформацияОбОшибке - описание возникшей ошибки.
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы.
|
||
//
|
||
Процедура ПриАварийномЗавершенииПотокаПоискаПорцииДляОбновления(Поток, ИнформацияОбОшибке) Экспорт
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(Поток.ПараметрыПроцедуры.ИмяОбработчика);
|
||
Описание = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
Описание.ВыполняетсяПоискПорции = Ложь;
|
||
УстановитьСвойствоОбработчика(Поток.ПараметрыПроцедуры.ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(Описание));
|
||
|
||
КонецПроцедуры
|
||
|
||
// Обработчик отмены выполнения потока поиска порции для обновления.
|
||
//
|
||
// Параметры:
|
||
// Поток - см. НовоеОписаниеПотоков
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
Процедура ПриОтменеПотокаПоискаПорцииДляОбновления(Поток) Экспорт
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(Поток.ПараметрыПроцедуры.ИмяОбработчика);
|
||
Описание = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
Описание.ВыполняетсяПоискПорции = Ложь;
|
||
УстановитьСвойствоОбработчика(Поток.ПараметрыПроцедуры.ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(Описание));
|
||
|
||
КонецПроцедуры
|
||
|
||
// Завершить обработку данных многопоточного обработчика обновления.
|
||
// Удалить обработанную порцию данных.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
Процедура ЗавершитьВыполнениеМногопоточногоОбработчика(КонтекстОбработчика, ИмяОбработчика)
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(ИмяОбработчика);
|
||
|
||
ОписаниеПроцедурыЗаполнения = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
ПорцииДляОбновления = ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления;
|
||
|
||
Если ПорцииДляОбновления <> Неопределено
|
||
И КонтекстОбработчика.Параметры.Свойство("ОбновляемыеДанные") Тогда
|
||
ОбновляемыеДанные = КонтекстОбработчика.Параметры.ОбновляемыеДанные;
|
||
|
||
Если ОбновляемыеДанные <> Неопределено Тогда
|
||
Порция = ПорцииДляОбновления.Найти(ОбновляемыеДанные.Идентификатор, "Идентификатор");
|
||
|
||
Если Порция <> Неопределено Тогда
|
||
ПорцииДляОбновления.Удалить(Порция);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(ОписаниеПроцедурыЗаполнения));
|
||
|
||
КонецПроцедуры
|
||
|
||
// Отменить обработку данных многопоточного обработчика обновления.
|
||
// Отметить, что найденную порцию данных нужно будет обрабатывать повторно.
|
||
//
|
||
// Параметры:
|
||
// Поток - СтрокаТаблицыЗначений:
|
||
// * Наименование - Строка - произвольное наименование потока (используется в наименовании фонового задания).
|
||
// * Группа - Строка - имя группы с описанием потока.
|
||
// * ИдентификаторЗадания - УникальныйИдентификатор - уникальный идентификатор фонового задания.
|
||
// * ПараметрыПроцедуры - см. НовыйКонтекстОбработчика
|
||
// * ПараметрыПроцедурыЗавершения - Произвольный - параметры для ПроцедураЗавершения.
|
||
// * АдресРезультата - Строка - адрес временного хранилища для сохранения результата выполнения фонового задания.
|
||
// ОбработчикОбновления - СтрокаДереваЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
Процедура ОтменитьОбработкуДанныхМногопоточногоОбработчика(Поток, ОбработчикОбновления)
|
||
|
||
ОписаниеПроцедурыЗаполнения = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
ПорцииДляОбновления = ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления;
|
||
|
||
Если ПорцииДляОбновления <> Неопределено Тогда
|
||
ОбновляемыеДанные = Поток.ПараметрыПроцедуры.Параметры.ОбновляемыеДанные;
|
||
|
||
Если ОбновляемыеДанные <> Неопределено Тогда
|
||
Порция = ПорцииДляОбновления.Найти(ОбновляемыеДанные.Идентификатор, "Идентификатор");
|
||
|
||
Если Порция <> Неопределено Тогда
|
||
Порция.Обрабатывается = Ложь;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(ОписаниеПроцедурыЗаполнения));
|
||
|
||
КонецПроцедуры
|
||
|
||
// Сохранить результат первого поиска данных для многопоточного обработчика.
|
||
//
|
||
// Параметры:
|
||
// РезультатПоиска - см. НовыйРезультатПоискаПорции
|
||
// ОписаниеПроцедурыЗаполнения - см. НовоеОписаниеОбрабатываемыхДанных
|
||
//
|
||
Процедура СохранитьРезультатПервогоПоиска(РезультатПоиска, ОписаниеПроцедурыЗаполнения)
|
||
|
||
Если РезультатПоиска.Количество > 0 Тогда
|
||
ПоследняяВыбраннаяЗапись = КлючЗаписиПоследнейСтрокиНабораДанных(РезультатПоиска.НаборДанных);
|
||
ОписаниеПроцедурыЗаполнения.ПоследняяВыбраннаяЗапись = ПоследняяВыбраннаяЗапись;
|
||
|
||
Если ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления = Неопределено Тогда
|
||
ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления = НоваяТаблицаПорцийДляОбновления();
|
||
КонецЕсли;
|
||
Иначе
|
||
ОписаниеПроцедурыЗаполнения.ПоследняяВыбраннаяЗапись = Неопределено;
|
||
КонецЕсли;
|
||
|
||
ОписаниеПроцедурыЗаполнения.ПоискЗавершен = РезультатПоиска.ПоискЗавершен;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Сохранить результат повторного (после ошибки) поиска данных для многопоточного обработчика.
|
||
//
|
||
// Параметры:
|
||
// РезультатПоиска - см. НовыйРезультатПоискаПорции
|
||
// ОписаниеПроцедурыЗаполнения - см. НовоеОписаниеОбрабатываемыхДанных
|
||
// ИдентификаторПорции - УникальныйИдентификатор - идентификатор порции для которой искались данные.
|
||
//
|
||
Процедура СохранитьРезультатПовторногоПоиска(РезультатПоиска, ОписаниеПроцедурыЗаполнения, ИдентификаторПорции)
|
||
|
||
Если РезультатПоиска.Количество = 0 Тогда
|
||
ПорцииДляОбновления = ОписаниеПроцедурыЗаполнения.ПорцииДляОбновления;
|
||
Порция = ПорцииДляОбновления.Найти(ИдентификаторПорции, "Идентификатор");
|
||
ПорцииДляОбновления.Удалить(Порция);
|
||
КонецЕсли;
|
||
|
||
ОписаниеПроцедурыЗаполнения.ПоискЗавершен = РезультатПоиска.ПоискЗавершен;
|
||
|
||
Если ОписаниеПроцедурыЗаполнения.Свойство("ИмяОбработчика") Тогда
|
||
УстановитьСвойствоОбработчика(ОписаниеПроцедурыЗаполнения.ИмяОбработчика,
|
||
"ОбрабатываемыеДанные",
|
||
Новый ХранилищеЗначения(ОписаниеПроцедурыЗаполнения));
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Сохранить результат поиска данных для многопоточного обработчика.
|
||
//
|
||
// Параметры:
|
||
// РезультатПоиска - см. НовыйРезультатПоискаПорции
|
||
// ОписаниеПроцедурыЗаполнения - см. НовоеОписаниеОбрабатываемыхДанных
|
||
//
|
||
Процедура СохранитьРезультатПоиска(РезультатПоиска, ОписаниеПроцедурыЗаполнения)
|
||
|
||
Если РезультатПоиска.Количество > 0 Тогда
|
||
ПоследняяВыбраннаяЗапись = КлючЗаписиПоследнейСтрокиНабораДанных(РезультатПоиска.НаборДанных);
|
||
ОписаниеПроцедурыЗаполнения.ПоследняяВыбраннаяЗапись = ПоследняяВыбраннаяЗапись;
|
||
КонецЕсли;
|
||
|
||
ОписаниеПроцедурыЗаполнения.ПоискЗавершен = РезультатПоиска.ПоискЗавершен;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Разбить найденные данные на указанное количество порций.
|
||
//
|
||
// Параметры:
|
||
// РезультатПоиска - см. НовыйРезультатПоискаПорции
|
||
// КоличествоФрагментов - Число - количество фрагментов на которые нужно разбить данные.
|
||
//
|
||
// Возвращаемое значение:
|
||
// см. НовыйНаборПорцийДляОбновления
|
||
//
|
||
Функция РазбитьРезультатПоискаНаФрагменты(РезультатПоиска, Знач КоличествоФрагментов)
|
||
|
||
Фрагменты = НовыйНаборПорцийДляОбновления();
|
||
НайденныйНаборДанных = РезультатПоиска.НаборДанных;
|
||
КоличествоНайденных = РезультатПоиска.Количество;
|
||
КоличествоФрагментов = ?(КоличествоНайденных < КоличествоФрагментов, 1, КоличествоФрагментов);
|
||
МаксимальныйРазмерПорции = Цел(КоличествоНайденных / КоличествоФрагментов);
|
||
КоличествоОбработанных = 0;
|
||
|
||
Для НомерФрагмента = 1 По КоличествоФрагментов Цикл // Разбивка идет с конца найденного набора данных.
|
||
Фрагмент = НоваяПорцияДляОбновления();
|
||
Фрагмент.Идентификатор = Новый УникальныйИдентификатор;
|
||
Фрагмент.НаборДанных = НовыйНаборДанныхДляОбновления();
|
||
Фрагмент.ПоследняяЗапись = КлючЗаписиПоследнейСтрокиНабораДанных(НайденныйНаборДанных);
|
||
Фрагменты.Вставить(0, Фрагмент);
|
||
ИндексНабораДанных = НайденныйНаборДанных.Количество() - 1;
|
||
КоличествоСвободных = ?(НомерФрагмента = КоличествоФрагментов,
|
||
КоличествоНайденных - КоличествоОбработанных,
|
||
МаксимальныйРазмерПорции);
|
||
|
||
Пока ИндексНабораДанных >= 0 Цикл
|
||
ТекущаяСтрокаДанных = НайденныйНаборДанных[ИндексНабораДанных];
|
||
ТекущиеДанные = ТекущаяСтрокаДанных.Данные;
|
||
ТекущееКоличество = ТекущиеДанные.Количество();
|
||
ДанныеФрагмента = Фрагмент.НаборДанных.Добавить();
|
||
|
||
Если ТекущееКоличество <= КоличествоСвободных Тогда
|
||
ЗаполнитьЗначенияСвойств(ДанныеФрагмента, ТекущаяСтрокаДанных);
|
||
НайденныйНаборДанных.Удалить(ИндексНабораДанных);
|
||
КоличествоСвободных = КоличествоСвободных - ТекущееКоличество;
|
||
КоличествоОбработанных = КоличествоОбработанных + ТекущееКоличество;
|
||
Иначе
|
||
ЗаполнитьЗначенияСвойств(ДанныеФрагмента, ТекущаяСтрокаДанных, "СсылочныйОбъект, ТабличныйОбъект");
|
||
НачалоВырезки = ТекущееКоличество - КоличествоСвободных;
|
||
ДанныеФрагмента.Данные = ВырезатьСтрокиИзТаблицыЗначений(ТекущиеДанные, НачалоВырезки, КоличествоСвободных);
|
||
КоличествоОбработанных = КоличествоОбработанных + КоличествоСвободных;
|
||
КоличествоСвободных = 0;
|
||
КонецЕсли;
|
||
|
||
Если КоличествоСвободных = 0 Тогда
|
||
Прервать;
|
||
Иначе
|
||
ИндексНабораДанных = ИндексНабораДанных - 1;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Фрагмент.ПерваяЗапись = КлючЗаписиПервойСтрокиНабораДанных(Фрагмент.НаборДанных);
|
||
КонецЦикла;
|
||
|
||
Возврат Фрагменты;
|
||
|
||
КонецФункции
|
||
|
||
// Вырезать СуществующиеПоставляемыеЭлементы таблицы значений в новую таблицу значений.
|
||
//
|
||
// Параметры:
|
||
// Таблица - ТаблицаЗначений - таблица из которой вырезаются строки.
|
||
// Начало - Число - индекс первой вырезаемой строки.
|
||
// Количество - Число - количество вырезаемых строк.
|
||
//
|
||
// Возвращаемое значение:
|
||
// ТаблицаЗначений - вырезанные строки в виде новой таблицы значений.
|
||
//
|
||
Функция ВырезатьСтрокиИзТаблицыЗначений(Таблица, Начало, Количество)
|
||
|
||
НоваяТаблица = Таблица.СкопироватьКолонки();
|
||
Индекс = Начало + Количество - 1;
|
||
|
||
Пока Индекс >= Начало Цикл
|
||
НоваяСтрока = НоваяТаблица.Добавить();
|
||
СтараяСтрока = Таблица[Индекс];
|
||
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтараяСтрока);
|
||
Таблица.Удалить(СтараяСтрока);
|
||
Индекс = Индекс - 1;
|
||
КонецЦикла;
|
||
|
||
Возврат НоваяТаблица;
|
||
|
||
КонецФункции
|
||
|
||
// Определяет, есть ли в обработчике порции, которые можно было бы обновить в новом потоке.
|
||
//
|
||
// Параметры:
|
||
// ОбработчикОбновления - СтрокаТаблицыЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
//
|
||
Функция ЕстьПорцииДляОбновления(ОбработчикОбновления)
|
||
|
||
Описание = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
|
||
Если Описание.ВыполняетсяПоискПорции Тогда
|
||
Возврат Ложь;
|
||
Иначе
|
||
Если Описание.ПорцииДляОбновления <> Неопределено И Описание.ПорцииДляОбновления.Количество() > 0 Тогда
|
||
Для каждого Порция Из Описание.ПорцииДляОбновления Цикл
|
||
Если Не Порция.Обрабатывается Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат Ложь;
|
||
Иначе
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
// Получить ключ записи первой строки набора данных.
|
||
//
|
||
// Параметры:
|
||
// НаборДанных - см. НовыйНаборДанныхДляОбновления
|
||
//
|
||
// Возвращаемое значение:
|
||
// СписокЗначений - ключ записи.
|
||
//
|
||
Функция КлючЗаписиПервойСтрокиНабораДанных(НаборДанных)
|
||
|
||
ПерваяСтрокаДанных = НаборДанных[0];
|
||
Возврат НовыйКлючЗаписиИзТаблицыДанных(ПерваяСтрокаДанных.СсылочныйОбъект,
|
||
ПерваяСтрокаДанных.ТабличныйОбъект,
|
||
ПерваяСтрокаДанных.Данные,
|
||
0);
|
||
|
||
КонецФункции
|
||
|
||
// Получить ключ записи последней строки набора данных.
|
||
//
|
||
// Параметры:
|
||
// НаборДанных - см. НовыйНаборДанныхДляОбновления
|
||
//
|
||
// Возвращаемое значение:
|
||
// СписокЗначений - ключ записи.
|
||
//
|
||
Функция КлючЗаписиПоследнейСтрокиНабораДанных(НаборДанных)
|
||
|
||
ПоследняяСтрокаДанных = НаборДанных[НаборДанных.Количество() - 1];
|
||
Возврат НовыйКлючЗаписиИзТаблицыДанных(ПоследняяСтрокаДанных.СсылочныйОбъект,
|
||
ПоследняяСтрокаДанных.ТабличныйОбъект,
|
||
ПоследняяСтрокаДанных.Данные,
|
||
ПоследняяСтрокаДанных.Данные.Количество() - 1);
|
||
|
||
КонецФункции
|
||
|
||
// Таблица с описанием порций обновляемых данных.
|
||
//
|
||
// Возвращаемое значение:
|
||
// ТаблицаЗначений:
|
||
// * Идентификатор - УникальныйИдентификатор - идентификатор порции.
|
||
// * ПерваяЗапись - СписокЗначений - первая запись в порции, где:
|
||
// ** Представление - Строка - имя поля.
|
||
// ** Значение - Произвольный - значение поля ключа.
|
||
// * ПоследняяЗапись - СписокЗначений - последняя запись в порции, где:
|
||
// ** Представление - Строка - имя поля.
|
||
// ** Значение - Произвольный - значение поля ключа.
|
||
// * Обрабатывается - Булево - Истина, если запущен поток обновления данных.
|
||
//
|
||
Функция НоваяТаблицаПорцийДляОбновления()
|
||
|
||
Таблица = Новый ТаблицаЗначений;
|
||
Колонки = Таблица.Колонки;
|
||
Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("УникальныйИдентификатор"));
|
||
Колонки.Добавить("ПерваяЗапись", Новый ОписаниеТипов("СписокЗначений"));
|
||
Колонки.Добавить("ПоследняяЗапись", Новый ОписаниеТипов("СписокЗначений"));
|
||
Колонки.Добавить("Обрабатывается", Новый ОписаниеТипов("Булево"));
|
||
Таблица.Индексы.Добавить("Идентификатор");
|
||
|
||
Возврат Таблица;
|
||
|
||
КонецФункции
|
||
|
||
// Описание обрабатываемых данных обработчика обновления (для СведенияОбОбновлении.ОбрабатываемыеДанные).
|
||
//
|
||
// Параметры:
|
||
// Многопоточное - Булево - Истина, если используется для многопоточного обработчика обновления.
|
||
// Фоновое - Булево - Истина, если используется для ЗаполнитьДанныеОтложенногоОбработчика().
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - описание со следующими полями:
|
||
// * ДанныеОбработчика - Соответствие - данные регистрируемые и обрабатываемые обработчиком обновления.
|
||
// * ВыполняетсяПоискПорции - Булево - признак наличия потока, выполняющего поиск порции данных для обновления.
|
||
// * ПараметрыВыборки - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки
|
||
// * ПорцииДляОбновления - см. НоваяТаблицаПорцийДляОбновления
|
||
// * ПоследняяВыбраннаяЗапись - СписокЗначений - описание начала отбора при страничной выборке:
|
||
// ** Представление - Строка - имя поля.
|
||
// ** Значение - Произвольный - значение поля.
|
||
// * ПоискЗавершен - Булево - Истина, поиск больше выполняться не будет (завершен).
|
||
// * ОбработкаЗавершена - Булево - признак завершения обработки, заполняемый обработчиком обновления.
|
||
// * ИмяОбработчика - Строка - имя обработчика обновления.
|
||
// * Очередь - Число - номер очереди обработчика обновления.
|
||
// * ПроцедураЗаполнения - Строка - имя процедуры заполнения данных для обновления.
|
||
// * Статус - Строка - статус обработки данных.
|
||
//
|
||
Функция НовоеОписаниеОбрабатываемыхДанных(Многопоточное = Ложь, Фоновое = Ложь) Экспорт
|
||
|
||
Описание = Новый Структура;
|
||
Описание.Вставить("ДанныеОбработчика");
|
||
Описание.Вставить("ИмяОбработчика");
|
||
|
||
Если Многопоточное Тогда
|
||
Описание.Вставить("ВыполняетсяПоискПорции", Ложь);
|
||
Описание.Вставить("ПараметрыВыборки");
|
||
Описание.Вставить("ПорцииДляОбновления");
|
||
Описание.Вставить("ПоследняяВыбраннаяЗапись");
|
||
Описание.Вставить("ПоискЗавершен", Ложь);
|
||
КонецЕсли;
|
||
|
||
Если Фоновое Тогда
|
||
Описание.Вставить("Очередь");
|
||
Описание.Вставить("ПроцедураЗаполнения");
|
||
Описание.Вставить("Статус");
|
||
КонецЕсли;
|
||
|
||
Возврат Описание;
|
||
|
||
КонецФункции
|
||
|
||
// Отбор для процедуры НайтиПорциюДляОбновления().
|
||
// Если заполнена ПоследняяВыбраннаяЗапись, то выполняется поиск первых 10000 записей после нее.
|
||
// Иначе выполняется поиск записей между ПерваяЗапись и ПоследняяЗапись.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - отбор со следующими полями:
|
||
// * ИдентификаторПорции - УникальныйИдентификатор - идентификатор порции для которой ищутся данные.
|
||
// * КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// * ПоследняяВыбраннаяЗапись - СписокЗначений - описание начала отбора при страничной выборке:
|
||
// ** Представление - Строка - имя поля.
|
||
// ** Значение - Произвольный - значение поля.
|
||
// * ПерваяЗапись - СписокЗначений - первая запись в порции, где:
|
||
// ** Представление - Строка - имя поля.
|
||
// ** Значение - Произвольный - значение поля ключа.
|
||
// * ПоследняяЗапись - СписокЗначений - последняя запись в порции, где:
|
||
// ** Представление - Строка - имя поля.
|
||
// ** Значение - Произвольный - значение поля ключа.
|
||
// * ПараметрыВыборки - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки
|
||
// * Очередь - Число - номер очереди обработчика.
|
||
//
|
||
Функция НовыеПараметрыПоискаПорции()
|
||
|
||
ПараметрыПоиска = Новый Структура;
|
||
ПараметрыПоиска.Вставить("ИдентификаторПорции");
|
||
ПараметрыПоиска.Вставить("ИмяОбработчика");
|
||
ПараметрыПоиска.Вставить("КонтекстОбработчика");
|
||
ПараметрыПоиска.Вставить("ПоследняяВыбраннаяЗапись");
|
||
ПараметрыПоиска.Вставить("ПерваяЗапись");
|
||
ПараметрыПоиска.Вставить("ПоследняяЗапись");
|
||
ПараметрыПоиска.Вставить("ПараметрыВыборки");
|
||
ПараметрыПоиска.Вставить("Очередь");
|
||
ПараметрыПоиска.Вставить("ФорсироватьОбновление", Ложь);
|
||
|
||
Возврат ПараметрыПоиска;
|
||
|
||
КонецФункции
|
||
|
||
// Ключ записи порции данных.
|
||
//
|
||
// Параметры:
|
||
// СсылочныйОбъект - Строка - полное имя объекта метаданных ссылочного типа.
|
||
// ТабличныйОбъект - Строка - полное имя объекта метаданных табличного типа.
|
||
//
|
||
// Возвращаемое значение:
|
||
// СписокЗначений из Строка
|
||
//
|
||
Функция НовыйКлючЗаписи(СсылочныйОбъект, ТабличныйОбъект)
|
||
|
||
КлючЗаписи = Новый СписокЗначений;
|
||
КлючЗаписи.Добавить(СсылочныйОбъект);
|
||
КлючЗаписи.Добавить(ТабличныйОбъект);
|
||
|
||
Возврат КлючЗаписи;
|
||
|
||
КонецФункции
|
||
|
||
// Ключ записи порции из таблицы с данными.
|
||
//
|
||
// Параметры:
|
||
// СсылочныйОбъект - Строка - полное имя объекта метаданных ссылочного типа.
|
||
// ТабличныйОбъект - Строка - полное имя объекта метаданных табличного типа.
|
||
// Данные - ТаблицаЗначений - данные порции.
|
||
// Индекс - Число - индекс строки данных для формирования ключа.
|
||
//
|
||
// Возвращаемое значение:
|
||
// СписокЗначений - ключ записи.
|
||
//
|
||
Функция НовыйКлючЗаписиИзТаблицыДанных(СсылочныйОбъект, ТабличныйОбъект, Данные, Индекс)
|
||
|
||
КлючЗаписи = НовыйКлючЗаписи(СсылочныйОбъект, ТабличныйОбъект);
|
||
Строка = Данные[Индекс];
|
||
|
||
Для каждого Колонка Из Данные.Колонки Цикл
|
||
ИмяКолонки = Колонка.Имя;
|
||
КлючЗаписи.Добавить(Строка[ИмяКолонки], ИмяКолонки);
|
||
КонецЦикла;
|
||
|
||
Возврат КлючЗаписи;
|
||
|
||
КонецФункции
|
||
|
||
// Таблица значений с описанием данных для обновления.
|
||
// Является результатом поиска данных для обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// ТаблицаЗначений - описание порций со следующей структурой:
|
||
// * СсылочныйОбъект - Строка - имя ссылочного объекта метаданных (может быть Неопределено).
|
||
// * ТабличныйОбъект - Строка - имя табличного объекта метаданных (может быть Неопределено).
|
||
// * Данные - ТаблицаЗначений - выборка из СУБД в виде таблицы значений.
|
||
//
|
||
Функция НовыйНаборДанныхДляОбновления()
|
||
|
||
НаборДанных = Новый ТаблицаЗначений;
|
||
Колонки = НаборДанных.Колонки;
|
||
Колонки.Добавить("СсылочныйОбъект", Новый ОписаниеТипов("Строка"));
|
||
Колонки.Добавить("ТабличныйОбъект", Новый ОписаниеТипов("Строка"));
|
||
Колонки.Добавить("Данные", Новый ОписаниеТипов("ТаблицаЗначений"));
|
||
|
||
Возврат НаборДанных;
|
||
|
||
КонецФункции
|
||
|
||
// Массив описаний порций данных для обновления.
|
||
// Является результатом разбиения найденных данных на фрагменты.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Массив из см. НоваяПорцияДляОбновления
|
||
//
|
||
Функция НовыйНаборПорцийДляОбновления()
|
||
|
||
Возврат Новый Массив;
|
||
|
||
КонецФункции
|
||
|
||
// Описание порции данных для обновления.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - описание порции со следующей структурой:
|
||
// * Идентификатор - УникальныйИдентификатор - идентификатор порции.
|
||
// * ПерваяЗапись - СписокЗначений - ключ первой записи порции, см. НовыйКлючЗаписиИзДанныхПорции.
|
||
// * ПоследняяЗапись - СписокЗначений - ключ последней записи порции, см. НовыйКлючЗаписиИзДанныхПорции.
|
||
// * НаборДанных - см. НовыйНаборДанныхДляОбновления
|
||
//
|
||
Функция НоваяПорцияДляОбновления()
|
||
|
||
Порция = Новый Структура;
|
||
Порция.Вставить("Идентификатор");
|
||
Порция.Вставить("ПерваяЗапись");
|
||
Порция.Вставить("ПоследняяЗапись");
|
||
Порция.Вставить("НаборДанных");
|
||
|
||
Возврат Порция;
|
||
|
||
КонецФункции
|
||
|
||
// Результат выполнения поиска порции.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - результат поиска со следующими полями:
|
||
// Количество - Число - количество выбранных записей.
|
||
// НаборДанных - см. НовыйНаборДанныхДляОбновления
|
||
// ПоискЗавершен - Булево - Истина, если искать больше нечего.
|
||
//
|
||
Функция НовыйРезультатПоискаПорции()
|
||
|
||
РезультатПоиска = Новый Структура;
|
||
РезультатПоиска.Вставить("Количество", 0);
|
||
РезультатПоиска.Вставить("НаборДанных");
|
||
РезультатПоиска.Вставить("ПоискЗавершен", Ложь);
|
||
|
||
Возврат РезультатПоиска;
|
||
|
||
КонецФункции
|
||
|
||
// Найти первую не обработанную порцию (обработка которой завершилась аварийно).
|
||
//
|
||
// Параметры:
|
||
// ПорцииДляОбновления - см. НоваяТаблицаПорцийДляОбновления
|
||
//
|
||
// Возвращаемое значение:
|
||
// СтрокаТаблицыЗначений - найденная порция.
|
||
// Неопределено - если необработанных порций нет.
|
||
//
|
||
Функция ПерваяНеобработаннаяПорция(ПорцииДляОбновления)
|
||
|
||
Если ПорцииДляОбновления <> Неопределено Тогда
|
||
Для каждого Порция Из ПорцииДляОбновления Цикл
|
||
Если Не Порция.Обрабатывается Тогда
|
||
Возврат Порция;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Возврат Неопределено;
|
||
|
||
КонецФункции
|
||
|
||
// Аналог СтрРазделить, дополненный тем, что фрагменты сокращены слева и справа.
|
||
//
|
||
// Параметры:
|
||
// Строка - Строка - разделяемая строка.
|
||
// Разделитель - Строка - разделитель элементов строки.
|
||
// ВключатьПустые - Булево - Истина, если в результат попадают пустые строки.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Массив - элементы строки, разбитые по разделителю.
|
||
//
|
||
Функция СтрРазделитьСокрЛП(Строка, Разделитель, ВключатьПустые = Истина)
|
||
|
||
Массив = СтрРазделить(Строка, Разделитель, ВключатьПустые);
|
||
|
||
Для Индекс = 0 По Массив.ВГраница() Цикл
|
||
Массив[Индекс] = СокрЛП(Массив[Индекс]);
|
||
КонецЦикла;
|
||
|
||
Возврат Массив;
|
||
|
||
КонецФункции
|
||
|
||
// Определяет, является ли описание обработчика многопоточным.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина, если описание многопоточное.
|
||
//
|
||
Функция ЭтоОписаниеДанныхМногопоточногоОбработчика(Описание)
|
||
|
||
Возврат Описание.Свойство("ПорцииДляОбновления");
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// НАЧАЛЬНОЕ ЗАПОЛНЕНИЕ ИНФОРМАЦИОННОЙ БАЗЫ
|
||
|
||
// Зарегистрировать предопределенные элементы для обновления в обработчике обновления.
|
||
//
|
||
Процедура ЗарегистрироватьПредопределенныеЭлементыДляОбновления(Параметры, ОбъектМетаданных = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
|
||
|
||
ПараметрыРегистрации = ПараметрыРегистрацииПредопределенныхЭлементов();
|
||
|
||
Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда
|
||
ЗаполнитьЗначенияСвойств(ПараметрыРегистрации, ДополнительныеПараметры);
|
||
КонецЕсли;
|
||
|
||
ОбъектыСПредопределеннымиЭлементами = ?(ОбъектМетаданных <> Неопределено,
|
||
ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ОбъектМетаданных),
|
||
ОбъектыСНачальнымЗаполнением());
|
||
|
||
ОбъектыКОбработке = Новый Массив;
|
||
|
||
ШаблонаЗапроса = "ВЫБРАТЬ
|
||
| &Поля
|
||
|ИЗ
|
||
| #Таблица КАК Таблица
|
||
|ГДЕ
|
||
| Таблица.Предопределенный = ИСТИНА";
|
||
|
||
Для каждого ОбъектМетаданныхСЭлементами Из ОбъектыСПредопределеннымиЭлементами Цикл
|
||
|
||
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ОбъектМетаданныхСЭлементами.ПолноеИмя());
|
||
ЛокализуемыеРеквизитыОбъекта = Новый Соответствие;
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
ЛокализуемыеРеквизитыОбъекта = МодульМультиязычностьСервер.МультиязычныеРеквизитыОбъекта(ОбъектМетаданныхСЭлементами);
|
||
КонецЕсли;
|
||
|
||
ПредопределенныеДанные = ПредопределенныеДанныеОбъекта(ОбъектМетаданныхСЭлементами, МенеджерОбъекта, ЛокализуемыеРеквизитыОбъекта);
|
||
|
||
// Формируем запрос
|
||
|
||
ИменаРеквизитовОбъекта = Новый Массив;
|
||
Если ПараметрыРегистрации.РежимОбновления = "НовыеИИзмененные" Тогда
|
||
|
||
Для Каждого Колонка Из ПредопределенныеДанные.Колонки Цикл
|
||
Если ПустаяСтрока(Колонка.Заголовок) Тогда
|
||
ИменаРеквизитовОбъекта.Добавить(Колонка.Имя);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
МодульМультиязычностьСервер.СформироватьИменаМультиязычныхРеквизитов(ИменаРеквизитовОбъекта, ЛокализуемыеРеквизитыОбъекта);
|
||
КонецЕсли;
|
||
|
||
Если ИменаРеквизитовОбъекта.Найти("ИмяПредопределенныхДанных") = Неопределено Тогда
|
||
ИменаРеквизитовОбъекта.Добавить("ИмяПредопределенныхДанных");
|
||
КонецЕсли;
|
||
Если ИменаРеквизитовОбъекта.Найти("Ссылка") = Неопределено Тогда
|
||
ИменаРеквизитовОбъекта.Добавить("Ссылка");
|
||
КонецЕсли;
|
||
|
||
ТекстЗапроса = СтрЗаменить(ШаблонаЗапроса, "&Поля", СтрСоединить(ИменаРеквизитовОбъекта, ", " + Символы.ПС));
|
||
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#Таблица", ОбъектМетаданныхСЭлементами.ПолноеИмя());
|
||
Запрос = Новый Запрос(ТекстЗапроса);
|
||
|
||
РезультатЗапроса = Запрос.Выполнить();
|
||
Если РезультатЗапроса.Пустой() Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ДанныеЗапроса = РезультатЗапроса.Выбрать();
|
||
Пока ДанныеЗапроса.Следующий() Цикл
|
||
|
||
ПоставляемыеСведения = ПредопределенныеДанные.Найти(ДанныеЗапроса.ИмяПредопределенныхДанных, "ИмяПредопределенныхДанных");
|
||
|
||
Если ПоставляемыеСведения <> Неопределено Тогда
|
||
|
||
Если ПараметрыРегистрации.РежимОбновления = "Все" Тогда
|
||
ОбъектыКОбработке.Добавить(ДанныеЗапроса.Ссылка);
|
||
ИначеЕсли ПараметрыРегистрации.РежимОбновления = "НовыеИИзмененные" Тогда
|
||
|
||
Если ДанныеСодержатОтличия(ДанныеЗапроса, ИменаРеквизитовОбъекта, ПоставляемыеСведения, ЛокализуемыеРеквизитыОбъекта, ПараметрыРегистрации) Тогда
|
||
ОбъектыКОбработке.Добавить(ДанныеЗапроса.Ссылка);
|
||
КонецЕсли;
|
||
|
||
ИначеЕсли ПараметрыРегистрации.РежимОбновления = "МультиязычныеСтроки" Тогда
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
Если МодульМультиязычностьСервер.МультиязычныеСтрокиРеквизитовИзменены(
|
||
ПоставляемыеСведения, ДанныеЗапроса, ЛокализуемыеРеквизитыОбъекта, ПараметрыРегистрации) Тогда
|
||
ОбъектыКОбработке.Добавить(ДанныеЗапроса.Ссылка);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
КонецЦикла;
|
||
|
||
Если ОбъектыКОбработке.Количество() > 0 Тогда
|
||
ОбновлениеИнформационнойБазы.ОтметитьКОбработке(Параметры, ОбъектыКОбработке);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Заполнить объект начальными данными.
|
||
//
|
||
// Параметры:
|
||
// ЗаполняемыйОбъект - СправочникОбъект
|
||
// - ПланВидовХарактеристикОбъект
|
||
// - ДанныеФормыСтруктура:
|
||
// * Ссылка - СправочникСсылка
|
||
// НастройкиЗаполнения - см. ОбновлениеИнформационнойБазы.НастройкиЗаполнения
|
||
//
|
||
Процедура ЗаполнитьОбъектНачальнымиДанными(ЗаполняемыйОбъект, НастройкиЗаполнения) Экспорт
|
||
|
||
Если ТипЗнч(ЗаполняемыйОбъект) = Тип("ДанныеФормыСтруктура") Тогда
|
||
Если ЗаполняемыйОбъект.Свойство("ИсходныйКлючЗаписи") Тогда
|
||
ТипОбъекта = ТипЗнч(ЗаполняемыйОбъект.ИсходныйКлючЗаписи);
|
||
Иначе
|
||
ТипОбъекта = ТипЗнч(ЗаполняемыйОбъект.Ссылка);
|
||
КонецЕсли;
|
||
Иначе
|
||
ТипОбъекта = ТипЗнч(ЗаполняемыйОбъект);
|
||
КонецЕсли;
|
||
|
||
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипОбъекта);
|
||
|
||
НаборПараметровЗаполнения = НаборПараметровДляЗаполненияОбъекта(МетаданныеОбъекта);
|
||
|
||
ЗаполнитьРеквизитыНачальнымиДанными(ЗаполняемыйОбъект, НаборПараметровЗаполнения, НастройкиЗаполнения);
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ИмяКлючевогоРеквизита(НаборДанныхДляЗаполнения)
|
||
|
||
ИмяКлючевогоРеквизита = НаборДанныхДляЗаполнения.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита;
|
||
Если Не ЗначениеЗаполнено(ИмяКлючевогоРеквизита) Тогда
|
||
ИмяКлючевогоРеквизита = "ИмяПредопределенныхДанных";
|
||
КонецЕсли;
|
||
|
||
Возврат ИмяКлючевогоРеквизита;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ЗаполнитьЭлементыНачальнымиДанными(Параметры, ОбъектМетаданных, НастройкиЗаполнения) Экспорт
|
||
|
||
СсылкиНаОбъекты = ОбновлениеИнформационнойБазы.ВыбратьСсылкиДляОбработки(Параметры.Очередь, ОбъектМетаданных.ПолноеИмя());
|
||
|
||
Если НастройкиЗаполнения.ОбновитьТолькоМультиязычныеСтроки Тогда
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
Результат = МодульМультиязычностьСервер.ОбновитьМультиязычныеСтрокиПредопределенныхЭлементов(СсылкиНаОбъекты, ОбъектМетаданных);
|
||
КонецЕсли;
|
||
Иначе
|
||
Результат = ОбновитьЭлементыПредопределенныхЭлементов(СсылкиНаОбъекты, ОбъектМетаданных, НастройкиЗаполнения);
|
||
КонецЕсли;
|
||
|
||
Параметры.ОбработкаЗавершена = ОбновлениеИнформационнойБазы.ОбработкаДанныхЗавершена(Параметры.Очередь, ОбъектМетаданных.ПолноеИмя());
|
||
|
||
Если Результат.ОбъектовОбработано = 0 И Результат.ПроблемныхОбъектов <> 0 Тогда
|
||
ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Не удалось заполнить начальными данными некоторые элементы (пропущены): %1'"),
|
||
Результат.ПроблемныхОбъектов);
|
||
ВызватьИсключение ТекстСообщения;
|
||
Иначе
|
||
ЗаписьЖурналаРегистрации(ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Информация,
|
||
ОбъектМетаданных,, СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Обработана очередная порция элементов: %1'"),
|
||
Результат.ОбъектовОбработано));
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПараметрыРегистрацииПредопределенныхЭлементов()
|
||
|
||
ДополнительныеПараметры = Новый Структура;
|
||
ДополнительныеПараметры.Вставить("РежимОбновления", "НовыеИИзмененные");
|
||
ДополнительныеПараметры.Вставить("ПропускатьПустые", Истина);
|
||
ДополнительныеПараметры.Вставить("СравниватьТабличныеЧасти", Ложь);
|
||
|
||
Возврат ДополнительныеПараметры;
|
||
|
||
КонецФункции
|
||
|
||
Функция ДанныеСодержатОтличия(ДанныеЗапроса, ИмяРеквизитОбъекта, ПоставляемыеСведения, ЛокализуемыеРеквизитыОбъекта, ПараметрыРегистрации)
|
||
|
||
Для каждого ИмяРеквизитаОбъекта Из ИмяРеквизитОбъекта Цикл
|
||
|
||
Если СтрСравнить(ИмяРеквизитаОбъекта, "Предопределенный") = 0
|
||
Или СтрСравнить(ИмяРеквизитаОбъекта, "Ссылка") = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ИмяРеквизитаБезСуффиксаЯзык= ИмяРеквизитаОбъекта;
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
ИмяРеквизитаБезСуффиксаЯзык = МодульМультиязычностьСервер.ИмяРеквизитаБезСуффиксаЯзык(ИмяРеквизитаОбъекта);
|
||
КонецЕсли;
|
||
|
||
Если ЛокализуемыеРеквизитыОбъекта[ИмяРеквизитаБезСуффиксаЯзык] = Неопределено Тогда
|
||
|
||
Если ТипЗнч(ПоставляемыеСведения[ИмяРеквизитаОбъекта]) = Тип("ТаблицаЗначений")
|
||
И ТипЗнч(ДанныеЗапроса[ИмяРеквизитаОбъекта]) = Тип("РезультатЗапроса") Тогда
|
||
|
||
Если ПараметрыРегистрации.СравниватьТабличныеЧасти Тогда
|
||
ТаблицаДанных = ДанныеЗапроса[ИмяРеквизитаОбъекта].Выгрузить();
|
||
Если Не ОбщегоНазначения.КоллекцииИдентичны(ПоставляемыеСведения[ИмяРеквизитаОбъекта], ТаблицаДанных) Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Иначе
|
||
Если ПараметрыРегистрации.ПропускатьПустые И ПустаяСтрока(ПоставляемыеСведения[ИмяРеквизитаОбъекта]) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Если ПоставляемыеСведения[ИмяРеквизитаОбъекта] <> ДанныеЗапроса[ИмяРеквизитаОбъекта] Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Иначе
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
Если МодульМультиязычностьСервер.МультиязычныеСтрокиРеквизитаИзменены(ПоставляемыеСведения, ДанныеЗапроса,
|
||
ИмяРеквизитаБезСуффиксаЯзык, ПараметрыРегистрации) Тогда
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
Возврат Ложь;
|
||
|
||
КонецФункции
|
||
|
||
// Общие для начального заполнения
|
||
|
||
|
||
// Переопределяемые настройки заполнения элементов
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ПриНачальномЗаполненииЭлемента - Булево
|
||
// * ИмяКлючевогоРеквизита - Строка
|
||
// * ДополнительныеПараметры - Структура
|
||
//
|
||
Функция ПользовательскиеНастройкиЗаполненияЭлементов()
|
||
|
||
НастройкиЗаполненияЭлементов = Новый Структура;
|
||
НастройкиЗаполненияЭлементов.Вставить("ПриНачальномЗаполненииЭлемента", Ложь);
|
||
НастройкиЗаполненияЭлементов.Вставить("ИмяКлючевогоРеквизита", "ИмяПредопределенныхДанных");
|
||
НастройкиЗаполненияЭлементов.Вставить("ДополнительныеПараметры", Новый Структура);
|
||
|
||
Возврат НастройкиЗаполненияЭлементов;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ЗаполнитьРеквизитыНачальнымиДанными(ЗаполняемыйЭлемент, НаборДанныхДляЗаполнения, НастройкиЗаполнения)
|
||
|
||
ИмяКлючевогоРеквизита = ИмяКлючевогоРеквизита(НаборДанныхДляЗаполнения.НастройкиПредопределенныхЭлементов);
|
||
|
||
ЗначениеКлючаОбъекта = ЗаполняемыйЭлемент[ИмяКлючевогоРеквизита];
|
||
|
||
Если Не ЗначениеЗаполнено(ЗначениеКлючаОбъекта) Тогда
|
||
|
||
Если Не НаборДанныхДляЗаполнения.НастройкиПредопределенныхЭлементов.ЕстьКолонкаИмяПредопределенныхДанных Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
ИмяКлючевогоРеквизита = "ИмяПредопределенныхДанных";
|
||
ЗначениеКлючаОбъекта = ЗаполняемыйЭлемент[ИмяКлючевогоРеквизита];
|
||
Если Не ЗначениеЗаполнено(ЗначениеКлючаОбъекта) Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
МенеджерОбъекта = НаборДанныхДляЗаполнения.МенеджерОбъекта;
|
||
|
||
СтрокаТаблицы = НаборДанныхДляЗаполнения.ПредопределенныеДанные.Найти(ЗначениеКлючаОбъекта, ИмяКлючевогоРеквизита);
|
||
Если СтрокаТаблицы = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
КромеРеквизитов = НаборДанныхДляЗаполнения.РеквизитыИсключения;
|
||
|
||
Если НаборДанныхДляЗаполнения.ПоддерживаетсяИерархия И ЗаполняемыйЭлемент.ЭтоГруппа Тогда
|
||
|
||
КромеРеквизитов = НаборДанныхДляЗаполнения.РеквизитыИсключения
|
||
+ ?(ПустаяСтрока(НаборДанныхДляЗаполнения.РеквизитыИсключения), "", ",") + СтрСоединить(НаборДанныхДляЗаполнения.РеквизитыСЭлементами, ",");
|
||
КонецЕсли;
|
||
|
||
Если Не НастройкиЗаполнения.ОбновитьТолькоМультиязычныеСтроки Тогда
|
||
|
||
Если ЗначениеЗаполнено(НастройкиЗаполнения.Реквизиты) Тогда
|
||
ЗаполнитьЗначенияСвойств(ЗаполняемыйЭлемент, СтрокаТаблицы, НастройкиЗаполнения.Реквизиты);
|
||
Иначе
|
||
ЗаполнитьЗначенияСвойств(ЗаполняемыйЭлемент, СтрокаТаблицы,, КромеРеквизитов);
|
||
КонецЕсли;
|
||
|
||
Если НаборДанныхДляЗаполнения.ПоддерживаетсяИерархия И ЗначениеЗаполнено(СтрокаТаблицы.Родитель) Тогда
|
||
|
||
Если ИмяКлючевогоРеквизита = "Ссылка" Тогда
|
||
Если ТипЗнч(СтрокаТаблицы.Родитель) = Тип("Строка") Тогда
|
||
ЗаполняемыйЭлемент.Родитель = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаТаблицы.Родитель));
|
||
ИначеЕсли ТипЗнч(СтрокаТаблицы.Родитель) = Тип("УникальныйИдентификатор") Тогда
|
||
ЗаполняемыйЭлемент.Родитель = МенеджерОбъекта.ПолучитьСсылку(СтрокаТаблицы.Родитель);
|
||
Иначе
|
||
ЗаполняемыйЭлемент.Родитель = СтрокаТаблицы.Родитель;
|
||
КонецЕсли;
|
||
ИначеЕсли ТипЗнч(СтрокаТаблицы.Родитель) = Тип("Строка") Тогда
|
||
|
||
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(ЗаполняемыйЭлемент));
|
||
СуществующиеЭлементы = СуществующиеПоставляемыеЭлементы(НаборДанныхДляЗаполнения.ПредопределенныеДанные,
|
||
НаборДанныхДляЗаполнения.НастройкиПредопределенныхЭлементов, МенеджерОбъекта, МетаданныеОбъекта);
|
||
ЗаполняемыйЭлемент.Родитель = СуществующиеЭлементы[СтрокаТаблицы.Родитель];
|
||
|
||
Иначе
|
||
ЗаполняемыйЭлемент.Родитель = СтрокаТаблицы.Родитель;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
Если НЕ (НаборДанныхДляЗаполнения.ПоддерживаетсяИерархия И ЗаполняемыйЭлемент.ЭтоГруппа) Тогда
|
||
Для Каждого ИмяТабличнойЧасти Из НаборДанныхДляЗаполнения.ТабличныеЧасти Цикл
|
||
ЗаполняемыйЭлемент[ИмяТабличнойЧасти].Загрузить(СтрокаТаблицы[ИмяТабличнойЧасти]);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
МодульМультиязычностьСервер.ЗаполнитьЭлементыМультиязычнымиНачальнымиДанными(ЗаполняемыйЭлемент,
|
||
НаборДанныхДляЗаполнения.ЛокализуемыеРеквизитыОбъекта, НаборДанныхДляЗаполнения.МультиязычныеСтрокиВРеквизитах,
|
||
НаборДанныхДляЗаполнения.ПоддерживаетсяИерархия, СтрокаТаблицы);
|
||
КонецЕсли;
|
||
|
||
Если НаборДанныхДляЗаполнения.НастройкиПредопределенныхЭлементов.ПереопределяемыеНастройки.ПриНачальномЗаполненииЭлемента Тогда
|
||
МенеджерОбъекта.ПриНачальномЗаполненииЭлемента(ЗаполняемыйЭлемент, СтрокаТаблицы, НаборДанныхДляЗаполнения.НастройкиПредопределенныхЭлементов.ПереопределяемыеНастройки.ДополнительныеПараметры);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Обновить элементы предопределенных элементов в обработчиках обновления
|
||
//
|
||
// Параметры:
|
||
// СсылкиНаОбъекты - ВыборкаИзРезультатаЗапроса - ссылки на объекты:
|
||
// * Ссылка - ЛюбаяСсылка
|
||
// МетаданныеОбъекта - ОбъектМетаданных
|
||
// НастройкиЗаполнения - см. ОбновлениеИнформационнойБазы.НастройкиЗаполнения
|
||
//
|
||
// Возвращаемое значение:
|
||
// Структура - обновить элементы предопределенных элементов:
|
||
// * ПроблемныхОбъектов - Число
|
||
// * ОбъектовОбработано - Число
|
||
//
|
||
Функция ОбновитьЭлементыПредопределенныхЭлементов(СсылкиНаОбъекты, МетаданныеОбъекта, НастройкиЗаполнения)
|
||
|
||
Результат = Новый Структура();
|
||
Результат.Вставить("ПроблемныхОбъектов", 0);
|
||
Результат.Вставить("ОбъектовОбработано", 0);
|
||
|
||
ПараметрыДляЗаполненияОбъекта = НаборПараметровДляЗаполненияОбъекта(МетаданныеОбъекта);
|
||
|
||
ИмяКлючевогоРеквизита = ИмяКлючевогоРеквизита(ПараметрыДляЗаполненияОбъекта.НастройкиПредопределенныхЭлементов);
|
||
|
||
ПоддерживаетсяИерархия = ПараметрыДляЗаполненияОбъекта.ПоддерживаетсяИерархия;
|
||
РеквизитыИсключения = ПараметрыДляЗаполненияОбъекта.РеквизитыИсключения;
|
||
МенеджерОбъекта = ПараметрыДляЗаполненияОбъекта.МенеджерОбъекта;
|
||
|
||
Пока СсылкиНаОбъекты.Следующий() Цикл
|
||
|
||
СсылкаНаОбъект = СсылкиНаОбъекты.Ссылка;
|
||
|
||
ЗначениеКлючевогоРеквизита = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаОбъект, ИмяКлючевогоРеквизита);
|
||
Если Не ЗначениеЗаполнено(ЗначениеКлючевогоРеквизита) Тогда
|
||
Результат.ОбъектовОбработано = Результат.ОбъектовОбработано + 1;
|
||
ОбновлениеИнформационнойБазы.ОтметитьВыполнениеОбработки(СсылкиНаОбъекты.Ссылка);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
СтрокаТаблицы = ПараметрыДляЗаполненияОбъекта.ПредопределенныеДанные.Найти(ЗначениеКлючевогоРеквизита, ИмяКлючевогоРеквизита);
|
||
Если СтрокаТаблицы = Неопределено Тогда
|
||
Результат.ОбъектовОбработано = Результат.ОбъектовОбработано + 1;
|
||
ОбновлениеИнформационнойБазы.ОтметитьВыполнениеОбработки(СсылкиНаОбъекты.Ссылка);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
НачатьТранзакцию();
|
||
|
||
Попытка
|
||
|
||
БлокировкаДанных = Новый БлокировкаДанных;
|
||
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(МетаданныеОбъекта.ПолноеИмя());
|
||
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкиНаОбъекты.Ссылка);
|
||
БлокировкаДанных.Заблокировать();
|
||
|
||
ЗаполняемыйЭлемент = СсылкиНаОбъекты.Ссылка.ПолучитьОбъект();
|
||
|
||
КромеРеквизитов = РеквизитыИсключения;
|
||
Если ПоддерживаетсяИерархия И ЗаполняемыйЭлемент.ЭтоГруппа Тогда
|
||
КромеРеквизитов = РеквизитыИсключения
|
||
+ ?(ПустаяСтрока(РеквизитыИсключения), "", ",") + СтрСоединить(ПараметрыДляЗаполненияОбъекта.РеквизитыСЭлементами, ",");
|
||
КонецЕсли;
|
||
|
||
Если ЗначениеЗаполнено(НастройкиЗаполнения.Реквизиты) Тогда
|
||
ЗаполнитьЗначенияСвойств(ЗаполняемыйЭлемент, СтрокаТаблицы, НастройкиЗаполнения.Реквизиты);
|
||
Иначе
|
||
ЗаполнитьЗначенияСвойств(ЗаполняемыйЭлемент, СтрокаТаблицы,, КромеРеквизитов);
|
||
КонецЕсли;
|
||
|
||
Если НЕ (ПоддерживаетсяИерархия И ЗаполняемыйЭлемент.ЭтоГруппа) Тогда
|
||
Для Каждого ИмяТабличнойЧасти Из ПараметрыДляЗаполненияОбъекта.ТабличныеЧасти Цикл
|
||
ЗаполняемыйЭлемент[ИмяТабличнойЧасти].Загрузить(СтрокаТаблицы[ИмяТабличнойЧасти]);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
МодульМультиязычностьСервер.ЗаполнитьЭлементыМультиязычнымиНачальнымиДанными(ЗаполняемыйЭлемент,
|
||
ПараметрыДляЗаполненияОбъекта.ЛокализуемыеРеквизитыОбъекта, ПараметрыДляЗаполненияОбъекта.МультиязычныеСтрокиВРеквизитах,
|
||
ПоддерживаетсяИерархия, СтрокаТаблицы);
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыДляЗаполненияОбъекта.НастройкиПредопределенныхЭлементов.ПереопределяемыеНастройки.ПриНачальномЗаполненииЭлемента Тогда
|
||
МенеджерОбъекта.ПриНачальномЗаполненииЭлемента(ЗаполняемыйЭлемент, СтрокаТаблицы,
|
||
ПараметрыДляЗаполненияОбъекта.НастройкиПредопределенныхЭлементов.ПереопределяемыеНастройки.ДополнительныеПараметры);
|
||
КонецЕсли;
|
||
|
||
ОбновлениеИнформационнойБазы.ЗаписатьОбъект(ЗаполняемыйЭлемент);
|
||
ЗафиксироватьТранзакцию();
|
||
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
// Если не удалось обработать элемент, повторяем попытку снова.
|
||
Результат.ПроблемныхОбъектов = Результат.ПроблемныхОбъектов + 1;
|
||
|
||
ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Не удалось заполнить элемент: %1 по причине: %2'"),
|
||
СсылкиНаОбъекты.Ссылка, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
|
||
|
||
ЗаписьЖурналаРегистрации(ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Предупреждение,
|
||
МетаданныеОбъекта, СсылкиНаОбъекты.Ссылка, ТекстСообщения);
|
||
КонецПопытки;
|
||
|
||
Результат.ОбъектовОбработано = Результат.ОбъектовОбработано + 1;
|
||
|
||
КонецЦикла;
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция СуществующиеПоставляемыеЭлементы(ПредопределенныеДанные, НастройкиПредопределенныхЭлементов, Знач МенеджерОбъекта, МетаданныеОбъекта)
|
||
|
||
Результат = Новый Соответствие();
|
||
|
||
ИмяКлючевогоРеквизита = НастройкиПредопределенныхЭлементов.ПереопределяемыеНастройки.ИмяКлючевогоРеквизита;
|
||
ЕстьКолонкаИмяПредопределенныхДанных = НастройкиПредопределенныхЭлементов.ЕстьКолонкаИмяПредопределенныхДанных;
|
||
|
||
ИменаПредопределенных = МетаданныеОбъекта.ПолучитьИменаПредопределенных();
|
||
|
||
НаборКлючей = Новый ТаблицаЗначений();
|
||
Если ИмяКлючевогоРеквизита <> "Ссылка" Тогда
|
||
НаборКлючей.Колонки.Добавить("Ключ", ОбщегоНазначения.ОписаниеТипаСтрока(150));
|
||
Иначе
|
||
|
||
Массив = Новый Массив;
|
||
Массив.Добавить(ТипЗнч(МенеджерОбъекта.ПустаяСсылка()));
|
||
НаборКлючей.Колонки.Добавить("Ключ", Новый ОписаниеТипов(Массив));
|
||
|
||
КонецЕсли;
|
||
|
||
Результат = Новый Соответствие();
|
||
|
||
Если СтрСравнить(ИмяКлючевогоРеквизита, "ИмяПредопределенныхДанных") <> 0 Тогда
|
||
|
||
Для Каждого ПредопределенныйЭлемент Из ПредопределенныеДанные Цикл
|
||
|
||
Если ЕстьКолонкаИмяПредопределенныхДанных
|
||
И ЗначениеЗаполнено(ПредопределенныйЭлемент.ИмяПредопределенныхДанных)
|
||
И ИменаПредопределенных.Найти(ПредопределенныйЭлемент.ИмяПредопределенныхДанных) <> Неопределено Тогда
|
||
Результат.Вставить(ПредопределенныйЭлемент.ИмяПредопределенныхДанных, МенеджерОбъекта[ПредопределенныйЭлемент.ИмяПредопределенныхДанных]);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ЗначениеЗаполнено(ПредопределенныйЭлемент[ИмяКлючевогоРеквизита]) Тогда
|
||
|
||
НоваяСтрока = НаборКлючей.Добавить();
|
||
НоваяСтрока.Ключ = ПредопределенныйЭлемент[ИмяКлючевогоРеквизита];
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
Если НаборКлючей.Количество() > 0 Тогда
|
||
|
||
Запрос = Новый Запрос;
|
||
ТекстЗапроса = "ВЫБРАТЬ
|
||
| НаборКлючей.Ключ КАК ИмяКлючевогоРеквизита
|
||
|ПОМЕСТИТЬ НаборКлючей
|
||
|ИЗ
|
||
| &НаборКлючей КАК НаборКлючей
|
||
|;
|
||
|
|
||
|////////////////////////////////////////////////////////////////////////////////
|
||
|ВЫБРАТЬ
|
||
| ЕСТЬNULL(ТаблицаДанных.Ссылка, НЕОПРЕДЕЛЕНО) КАК Ссылка,
|
||
| НаборКлючей.ИмяКлючевогоРеквизита КАК ИмяКлючевогоРеквизита
|
||
|ИЗ
|
||
| НаборКлючей КАК НаборКлючей
|
||
| ЛЕВОЕ СОЕДИНЕНИЕ #Таблица КАК ТаблицаДанных
|
||
| ПО НаборКлючей.ИмяКлючевогоРеквизита = &ИмяПоля";
|
||
|
||
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяПоля", "ТаблицаДанных." + ИмяКлючевогоРеквизита);
|
||
Запрос.Текст = СтрЗаменить(ТекстЗапроса, "#Таблица", МетаданныеОбъекта.ПолноеИмя());
|
||
Запрос.УстановитьПараметр("НаборКлючей", НаборКлючей);
|
||
|
||
РезультатЗапроса = Запрос.Выполнить();
|
||
|
||
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
|
||
|
||
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
|
||
Результат.Вставить(ВыборкаДетальныеЗаписи.ИмяКлючевогоРеквизита, ВыборкаДетальныеЗаписи.Ссылка);
|
||
КонецЦикла;
|
||
|
||
КонецЕсли;
|
||
|
||
ИначеЕсли ЕстьКолонкаИмяПредопределенныхДанных Тогда
|
||
|
||
Для Каждого ПоставляемыйЭлемент Из ПредопределенныеДанные Цикл
|
||
|
||
Если ЗначениеЗаполнено(ПоставляемыйЭлемент["ИмяПредопределенныхДанных"]) Тогда
|
||
Результат.Вставить(ПоставляемыйЭлемент["ИмяПредопределенныхДанных"], МенеджерОбъекта[ПоставляемыйЭлемент[ИмяКлючевогоРеквизита]]);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецЕсли;
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ДобавитьКолонкуТаблицыПредопределенныхДанных(ПредопределенныеДанные, Реквизит, ЛокализуемыеРеквизиты, Языки)
|
||
|
||
Если СтрСравнить(Реквизит.Имя, "Родитель") = 0 Тогда
|
||
МассивТипов = Новый Массив;
|
||
Для Каждого ТипРеквизита Из Реквизит.Тип.Типы() Цикл
|
||
МассивТипов.Добавить(ТипРеквизита);
|
||
КонецЦикла;
|
||
МассивТипов.Добавить(Тип("Строка"));
|
||
|
||
ПараметрыСтроки = Новый КвалификаторыСтроки(150);
|
||
ТипРеквизита = Новый ОписаниеТипов(МассивТипов,, ПараметрыСтроки);
|
||
ИначеЕсли СтрСравнить(Реквизит.Имя, "Ссылка") = 0 Тогда
|
||
МассивТипов = Новый Массив;
|
||
Для Каждого ТипРеквизита Из Реквизит.Тип.Типы() Цикл
|
||
МассивТипов.Добавить(ТипРеквизита);
|
||
КонецЦикла;
|
||
МассивТипов.Добавить(Тип("Строка"));
|
||
МассивТипов.Добавить(Тип("УникальныйИдентификатор"));
|
||
|
||
ПараметрыСтроки = Новый КвалификаторыСтроки(150);
|
||
ТипРеквизита = Новый ОписаниеТипов(МассивТипов,, ПараметрыСтроки);
|
||
Иначе
|
||
ТипРеквизита = Реквизит.Тип;
|
||
КонецЕсли;
|
||
|
||
ПредопределенныеДанные.Колонки.Добавить(Реквизит.Имя, ТипРеквизита);
|
||
Если ЛокализуемыеРеквизиты[Реквизит.Имя] = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
|
||
МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
|
||
Иначе
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Для Каждого Язык Из Языки Цикл
|
||
ПредопределенныеДанные.Колонки.Добавить(Реквизит.Имя + "_" + Язык, Реквизит.Тип,
|
||
МодульМультиязычностьСервер.ПризнакЛокализуемогоРеквизита());
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// ОБРАБОТЧИКИ ОБНОВЛЕНИЯ ИНФОРМАЦИОННОЙ БАЗЫ
|
||
|
||
// Устанавливает ключ регламентного задания ОтложенноеОбновлениеИБ.
|
||
//
|
||
Процедура УстановитьКлючРегламентногоЗадания() Экспорт
|
||
|
||
Отбор = Новый Структура;
|
||
Отбор.Вставить("Метаданные", Метаданные.РегламентныеЗадания.ОтложенноеОбновлениеИБ);
|
||
Отбор.Вставить("Предопределенное", Истина);
|
||
Задания = РегламентныеЗаданияСервер.НайтиЗадания(Отбор);
|
||
Для Каждого Задание Из Задания Цикл
|
||
Если ЗначениеЗаполнено(Задание.Ключ) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Задание.Ключ = Метаданные.РегламентныеЗадания.ОтложенноеОбновлениеИБ.Ключ;
|
||
Задание.Записать(); // АПК:1363 регламентное задание не участвует в обменах.
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Общего назначения
|
||
|
||
Процедура ОтключитьОбновлениеКлючейДоступа(Значение, ПодсистемаСуществует)
|
||
Если ПодсистемаСуществует Тогда
|
||
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
|
||
МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Значение);
|
||
КонецЕсли;
|
||
КонецПроцедуры
|
||
|
||
Функция РежимОбновленияДанныхВЛокальномРежимеРаботы()
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| 1 КАК ЕстьВерсииПодсистем
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем";
|
||
|
||
РезультатВыполненияПакета = Запрос.ВыполнитьПакет();
|
||
Если РезультатВыполненияПакета[0].Пустой() Тогда
|
||
Возврат "НачальноеЗаполнение";
|
||
КонецЕсли;
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| 1 КАК ЕстьВерсииПодсистем
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
|
||
|ГДЕ
|
||
| ВерсииПодсистем.ЭтоОсновнаяКонфигурация = ИСТИНА
|
||
|;
|
||
|
|
||
|////////////////////////////////////////////////////////////////////////////////
|
||
|ВЫБРАТЬ
|
||
| 1 КАК ЕстьВерсииПодсистем
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
|
||
|ГДЕ
|
||
| ВерсииПодсистем.ИмяПодсистемы = &ИмяОсновнойКонфигурации
|
||
|;
|
||
|
|
||
|////////////////////////////////////////////////////////////////////////////////
|
||
|ВЫБРАТЬ
|
||
| 1 КАК ЕстьВерсииПодсистем
|
||
|ИЗ
|
||
| РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
|
||
|ГДЕ
|
||
| ВерсииПодсистем.ЭтоОсновнаяКонфигурация = ИСТИНА
|
||
| И ВерсииПодсистем.ИмяПодсистемы = &ИмяОсновнойКонфигурации";
|
||
Запрос.УстановитьПараметр("ИмяОсновнойКонфигурации", Метаданные.Имя);
|
||
РезультатВыполненияПакета = Запрос.ВыполнитьПакет();
|
||
Если РезультатВыполненияПакета[0].Пустой() И Не РезультатВыполненияПакета[1].Пустой() Тогда
|
||
Возврат "ОбновлениеВерсии"; // Признак ЭтоОсновнаяКонфигурация еще не был заполнен.
|
||
КонецЕсли;
|
||
|
||
// Определяем по ранее заполненному признаку ЭтоОсновнаяКонфигурация.
|
||
Возврат ?(РезультатВыполненияПакета[2].Пустой(), "ПереходСДругойПрограммы", "ОбновлениеВерсии");
|
||
|
||
КонецФункции
|
||
|
||
// АПК:581-выкл используется для тестирования.
|
||
Функция ВозможноОперативноеОбновление(ПроверяемыеИтерацииОбновления = Неопределено) Экспорт
|
||
|
||
Если ПроверяемыеИтерацииОбновления = Неопределено Тогда
|
||
// Режим вызова для определения полного состава процедур обработчиков обновления,
|
||
// требующих монопольный режим (без записи сообщений в журнал регистрации).
|
||
ИтерацииОбновления = ИтерацииОбновления();
|
||
Иначе
|
||
ИтерацииОбновления = ПроверяемыеИтерацииОбновления;
|
||
КонецЕсли;
|
||
|
||
ФильтрыРазделенностиОбработчиков = Новый Массив;
|
||
Если НЕ ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
ФильтрыРазделенностиОбработчиков.Добавить(Ложь);
|
||
КонецЕсли;
|
||
ФильтрыРазделенностиОбработчиков.Добавить(Истина);
|
||
|
||
// В режиме проверки параметр не используется.
|
||
ОбязательныеРазделенныеОбработчики = ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления();
|
||
|
||
ЗаписыватьВЖурнал = Константы.ДетализироватьОбновлениеИБВЖурналеРегистрации.Получить();
|
||
ПроцедурыОбработчиков = Новый Массив;
|
||
|
||
// Проверяем обработчики обновления с флагом МонопольныйРежим для подсистем конфигурации.
|
||
Для каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
|
||
|
||
ПараметрыОтбора = ПараметрыОтбораОбработчиков();
|
||
ПараметрыОтбора.РежимОбновления = "Оперативно";
|
||
|
||
Для каждого ФлагРазделенности Из ФильтрыРазделенностиОбработчиков Цикл
|
||
|
||
ПараметрыОтбора.ПолучатьРазделенные = ФлагРазделенности;
|
||
|
||
ДеревоОбработчиков = ОбработчикиОбновленияВИнтервале(ИтерацияОбновления.Обработчики, ИтерацияОбновления.ПредыдущаяВерсия,
|
||
ИтерацияОбновления.Версия, ПараметрыОтбора);
|
||
Если ДеревоОбработчиков.Строки.Количество() = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ДеревоОбработчиков.Строки.Количество() > 1
|
||
ИЛИ ДеревоОбработчиков.Строки[0].Версия <> "*" Тогда
|
||
Для Каждого СтрокаВерсия Из ДеревоОбработчиков.Строки Цикл
|
||
Если СтрокаВерсия.Версия = "*" Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Для Каждого Обработчик Из СтрокаВерсия.Строки Цикл
|
||
ПроцедурыОбработчиков.Добавить(Обработчик.Процедура);
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Если ФлагРазделенности
|
||
И ОбщегоНазначения.РазделениеВключено()
|
||
И НЕ ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
// При обновлении неразделенной версии ИБ, для разделенных обязательных
|
||
// обработчиков обновления монопольным режимом управляет неразделенный обработчик.
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
НайденныеОбработчики = ДеревоОбработчиков.Строки[0].Строки.НайтиСтроки(Новый Структура("МонопольныйРежим", Неопределено));
|
||
Для Каждого Обработчик Из НайденныеОбработчики Цикл
|
||
ПроцедурыОбработчиков.Добавить(Обработчик.Процедура);
|
||
КонецЦикла;
|
||
|
||
// Вызов обязательных обработчиков обновления в режиме проверки.
|
||
Для каждого Обработчик Из ДеревоОбработчиков.Строки[0].Строки Цикл
|
||
Если Обработчик.ВерсияРегистрации <> "*" Тогда
|
||
ПроцедурыОбработчиков.Добавить(Обработчик.Процедура);
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ПараметрыОбработчика = Новый Структура;
|
||
Если Обработчик.УправлениеОбработчиками Тогда
|
||
ПараметрыОбработчика.Вставить("РазделенныеОбработчики", ОбязательныеРазделенныеОбработчики);
|
||
КонецЕсли;
|
||
ПараметрыОбработчика.Вставить("МонопольныйРежим", Ложь);
|
||
|
||
ДополнительныеПараметры = Новый Структура;
|
||
ДополнительныеПараметры.Вставить("ЗаписыватьВЖурнал", ЗаписыватьВЖурнал);
|
||
ДополнительныеПараметры.Вставить("ИдентификаторБиблиотеки", ИтерацияОбновления.Подсистема);
|
||
ДополнительныеПараметры.Вставить("ХодВыполненияОбработчиков", Неопределено);
|
||
ДополнительныеПараметры.Вставить("ВФоне", Ложь);
|
||
|
||
ВыполнитьОбработчикОбновления(Обработчик, ПараметрыОбработчика, ДополнительныеПараметры);
|
||
|
||
Если ПараметрыОбработчика.МонопольныйРежим = Истина Тогда
|
||
ПроцедурыОбработчиков.Добавить(Обработчик.Процедура);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
|
||
Если ПроверяемыеИтерацииОбновления = Неопределено Тогда
|
||
ПроверяемыеИтерацииОбновления = ПроцедурыОбработчиков;
|
||
Возврат ПроцедурыОбработчиков.Количество() = 0;
|
||
КонецЕсли;
|
||
|
||
Если ПроцедурыОбработчиков.Количество() <> 0 Тогда
|
||
ТекстСообщения = НСтр("ru = 'Следующие обработчики не поддерживают обновление без установки монопольного режима:'");
|
||
ТекстСообщения = ТекстСообщения + Символы.ПС;
|
||
Для Каждого ПроцедураОбработчика Из ПроцедурыОбработчиков Цикл
|
||
ТекстСообщения = ТекстСообщения + Символы.ПС + ПроцедураОбработчика;
|
||
КонецЦикла;
|
||
ЗаписатьОшибку(ТекстСообщения);
|
||
КонецЕсли;
|
||
|
||
Возврат ПроцедурыОбработчиков.Количество() = 0;
|
||
|
||
КонецФункции
|
||
// АПК:581-вкл.
|
||
|
||
Процедура СкопироватьСтрокиВДерево(Знач СтрокиПриемника, Знач СтрокиИсточника, Знач СтруктураКолонок)
|
||
|
||
Для каждого СтрокаИсточника Из СтрокиИсточника Цикл
|
||
ЗаполнитьЗначенияСвойств(СтруктураКолонок, СтрокаИсточника);
|
||
НайденныеСтроки = СтрокиПриемника.НайтиСтроки(СтруктураКолонок);
|
||
Если НайденныеСтроки.Количество() = 0 Тогда
|
||
СтрокаПриемника = СтрокиПриемника.Добавить();
|
||
ЗаполнитьЗначенияСвойств(СтрокаПриемника, СтрокаИсточника);
|
||
Иначе
|
||
СтрокаПриемника = НайденныеСтроки[0];
|
||
КонецЕсли;
|
||
|
||
СкопироватьСтрокиВДерево(СтрокаПриемника.Строки, СтрокаИсточника.Строки, СтруктураКолонок);
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПолучитьПланОбновления(Знач ИдентификаторБиблиотеки, Знач ВерсияС, Знач ВерсияНа)
|
||
|
||
МенеджерЗаписи = РегистрыСведений.ВерсииПодсистем.СоздатьМенеджерЗаписи();
|
||
МенеджерЗаписи.ИмяПодсистемы = ИдентификаторБиблиотеки;
|
||
МенеджерЗаписи.Прочитать();
|
||
Если НЕ МенеджерЗаписи.Выбран() Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
ОписаниеПлана = МенеджерЗаписи.ПланОбновления.Получить();
|
||
Если ОписаниеПлана = Неопределено Тогда
|
||
|
||
Возврат Неопределено;
|
||
|
||
Иначе
|
||
|
||
Если ОписаниеПлана.ВерсияС <> ВерсияС
|
||
ИЛИ ОписаниеПлана.ВерсияНа <> ВерсияНа Тогда
|
||
|
||
// План устарел и не соответствует текущей версии.
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
Возврат ОписаниеПлана.План;
|
||
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ВыполнитьОбработчикОбновления(Обработчик, Параметры, ДополнительныеПараметры)
|
||
|
||
ЗаписатьИнформациюОХодеОбновления(Обработчик, ДополнительныеПараметры.ХодВыполненияОбработчиков, ДополнительныеПараметры.ВФоне);
|
||
ОписаниеОбработчика =
|
||
ПодготовитьДетальнуюИнформациюОХодеОбновления(Обработчик, Параметры, ДополнительныеПараметры.ИдентификаторБиблиотеки);
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОценкаПроизводительности") Тогда
|
||
МодульОценкаПроизводительности = ОбщегоНазначения.ОбщийМодуль("ОценкаПроизводительности");
|
||
НачалоЗамера = МодульОценкаПроизводительности.НачатьЗамерВремени();
|
||
КонецЕсли;
|
||
|
||
Если Параметры <> Неопределено Тогда
|
||
ПараметрыОбработчика = Новый Массив;
|
||
ПараметрыОбработчика.Добавить(Параметры);
|
||
Иначе
|
||
ПараметрыОбработчика = Неопределено;
|
||
КонецЕсли;
|
||
|
||
ТранзакцияАктивнаНаНачалоВыполнения = ТранзакцияАктивна();
|
||
|
||
ПодсистемаСуществует = ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом");
|
||
ОтключитьОбновлениеКлючейДоступа(Истина, ПодсистемаСуществует);
|
||
Попытка
|
||
УстановитьПараметрыОбработчикаОбновления(Обработчик);
|
||
УстановитьСтатусОбработчика(Обработчик.Процедура, "Выполняется");
|
||
|
||
НачалоОбработки = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(Обработчик.Процедура, ПараметрыОбработчика);
|
||
КонецОбработки = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
|
||
УстановитьПараметрыОбработчикаОбновления(Неопределено);
|
||
|
||
УстанавливаемыеСвойства = Новый Структура;
|
||
УстанавливаемыеСвойства.Вставить("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
УстанавливаемыеСвойства.Вставить("ДлительностьОбработки", КонецОбработки - НачалоОбработки);
|
||
УстановитьСвойстваОбработчика(Обработчик.Процедура, УстанавливаемыеСвойства);
|
||
|
||
ОтключитьОбновлениеКлючейДоступа(Ложь, ПодсистемаСуществует);
|
||
Исключение
|
||
|
||
ОтключитьОбновлениеКлючейДоступа(Ложь, ПодсистемаСуществует);
|
||
Если ДополнительныеПараметры.ЗаписыватьВЖурнал Тогда
|
||
ЗаписатьДетальнуюИнформациюОХодеОбновления(ОписаниеОбработчика);
|
||
КонецЕсли;
|
||
|
||
ИмяОбработчика = Обработчик.Процедура + "(" + ?(ПараметрыОбработчика = Неопределено, "", "Параметры") + ")";
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'При вызове обработчика обновления:
|
||
|""%1""
|
||
|произошла ошибка:
|
||
|""%2"".'"),
|
||
ИмяОбработчика,
|
||
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
|
||
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
УстановитьСтатусОбработчика(Обработчик.Процедура, "Ошибка", ТекстОшибки);
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
ПроверитьВложеннуюТранзакцию(ТранзакцияАктивнаНаНачалоВыполнения, Обработчик.Процедура);
|
||
|
||
Если ДополнительныеПараметры.ЗаписыватьВЖурнал Тогда
|
||
ЗаписатьДетальнуюИнформациюОХодеОбновления(ОписаниеОбработчика);
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОценкаПроизводительности") Тогда
|
||
МодульОценкаПроизводительности = ОбщегоНазначения.ОбщийМодуль("ОценкаПроизводительности");
|
||
МодульОценкаПроизводительности.ЗакончитьЗамерВремениТехнологический("ВремяВыполненияОбработчикаОбновления." + ОписаниеОбработчика.Процедура, НачалоЗамера);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ВыполнитьОбработчикиПослеОбновленияИнформационнойБазы(Знач ИтерацииОбновления, Знач ЗаписыватьВЖурнал, ВыводитьОписаниеОбновлений, Знач ОперативноеОбновление)
|
||
|
||
Для Каждого ИтерацияОбновления Из ИтерацииОбновления Цикл
|
||
|
||
Если ЗаписыватьВЖурнал Тогда
|
||
Обработчик = Новый Структура();
|
||
Обработчик.Вставить("Версия", "*");
|
||
Обработчик.Вставить("ВерсияРегистрации", "*");
|
||
Обработчик.Вставить("РежимВыполнения", "Оперативно");
|
||
Обработчик.Вставить("Процедура", ИтерацияОбновления.ИмяОсновногоСерверногоМодуля + ".ПослеОбновленияИнформационнойБазы");
|
||
ОписаниеОбработчика = ПодготовитьДетальнуюИнформациюОХодеОбновления(Обработчик, Неопределено, ИтерацияОбновления.Подсистема);
|
||
КонецЕсли;
|
||
|
||
Попытка
|
||
|
||
ИтерацияОбновления.ОсновнойСерверныйМодуль.ПослеОбновленияИнформационнойБазы(
|
||
ИтерацияОбновления.ПредыдущаяВерсия,
|
||
ИтерацияОбновления.Версия,
|
||
ИтерацияОбновления.ВыполненныеОбработчики,
|
||
ВыводитьОписаниеОбновлений,
|
||
НЕ ОперативноеОбновление);
|
||
|
||
Исключение
|
||
|
||
Если ЗаписыватьВЖурнал Тогда
|
||
ЗаписатьДетальнуюИнформациюОХодеОбновления(ОписаниеОбработчика);
|
||
КонецЕсли;
|
||
|
||
ВызватьИсключение;
|
||
|
||
КонецПопытки;
|
||
|
||
Если ЗаписыватьВЖурнал Тогда
|
||
ЗаписатьДетальнуюИнформациюОХодеОбновления(ОписаниеОбработчика);
|
||
КонецЕсли;
|
||
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Параметры:
|
||
// Обработчик - Неопределено
|
||
// - СтрокаДереваЗначений
|
||
// - Структура:
|
||
// * РежимВыполнения - Строка
|
||
// * ВерсияРегистрации - Строка
|
||
// * Версия - Строка
|
||
// Параметры - Неопределено
|
||
// - Структура:
|
||
// * Очередь - Произвольный
|
||
// * ПрогрессВыполнения - Структура:
|
||
// ** ОбработаноОбъектов - Число
|
||
// ** ВсегоОбъектов - Число
|
||
// * ОбработкаЗавершена - Булево
|
||
// ИдентификаторБиблиотеки - Произвольный
|
||
// ОбработчикОтложенный - Булево
|
||
// Возвращаемое значение:
|
||
// Структура:
|
||
// * ЗначениеНаНачало - Число
|
||
// * ОбластьДанныхИспользование - Булево
|
||
// * ОбластьДанныхЗначение - Число
|
||
// * РежимВыполнения - Строка
|
||
// * Параметры - Неопределено
|
||
//
|
||
Функция ПодготовитьДетальнуюИнформациюОХодеОбновления(Обработчик, Параметры, ИдентификаторБиблиотеки, ОбработчикОтложенный = Ложь)
|
||
|
||
ОписаниеОбработчика = Новый Структура;
|
||
ОписаниеОбработчика.Вставить("Библиотека", ИдентификаторБиблиотеки);
|
||
Если ОбработчикОтложенный Тогда
|
||
ОписаниеОбработчика.Вставить("Версия", Обработчик.Версия);
|
||
ОписаниеОбработчика.Вставить("Процедура", Обработчик.ИмяОбработчика);
|
||
Иначе
|
||
ОписаниеОбработчика.Вставить("Версия", Обработчик.Версия);
|
||
ОписаниеОбработчика.Вставить("Процедура", Обработчик.Процедура);
|
||
КонецЕсли;
|
||
ОписаниеОбработчика.Вставить("ВерсияРегистрации", Обработчик.ВерсияРегистрации);
|
||
ОписаниеОбработчика.Вставить("Параметры", Параметры);
|
||
|
||
Если ОбработчикОтложенный Тогда
|
||
ОписаниеОбработчика.Вставить("РежимВыполнения", "Отложенно");
|
||
ИначеЕсли ЗначениеЗаполнено(Обработчик.РежимВыполнения) Тогда
|
||
ОписаниеОбработчика.Вставить("РежимВыполнения", Обработчик.РежимВыполнения);
|
||
Иначе
|
||
ОписаниеОбработчика.Вставить("РежимВыполнения", "Монопольно");
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
МодульРаботаВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаВМоделиСервиса");
|
||
|
||
ОписаниеОбработчика.Вставить("ОбластьДанныхЗначение",
|
||
МодульРаботаВМоделиСервиса.ЗначениеРазделителяСеанса());
|
||
ОписаниеОбработчика.Вставить("ОбластьДанныхИспользование", Истина);
|
||
|
||
Иначе
|
||
|
||
ОписаниеОбработчика.Вставить("ОбластьДанныхЗначение", -1);
|
||
ОписаниеОбработчика.Вставить("ОбластьДанныхИспользование", Ложь);
|
||
|
||
КонецЕсли;
|
||
|
||
ОписаниеОбработчика.Вставить("ЗначениеНаНачало", ТекущаяУниверсальнаяДатаВМиллисекундах());
|
||
|
||
Возврат ОписаниеОбработчика;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ЗаписатьДетальнуюИнформациюОХодеОбновления(ОписаниеОбработчика)
|
||
|
||
Длительность = ТекущаяУниверсальнаяДатаВМиллисекундах() - ОписаниеОбработчика.ЗначениеНаНачало;
|
||
|
||
ОписаниеОбработчика.Вставить("Выполнен", Ложь);
|
||
ОписаниеОбработчика.Вставить("Длительность", Длительность / 1000); // В секундах
|
||
|
||
КопияОписания = ОбщегоНазначения.СкопироватьРекурсивно(ОписаниеОбработчика);
|
||
Если КопияОписания.Свойство("Параметры") Тогда
|
||
КопияОписания.Удалить("Параметры");
|
||
КонецЕсли;
|
||
|
||
ЗаписьЖурналаРегистрации(
|
||
СобытиеЖурналаРегистрацииПротокол(),
|
||
УровеньЖурналаРегистрации.Информация,
|
||
,
|
||
,
|
||
ОбщегоНазначения.ЗначениеВСтрокуXML(КопияОписания));
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ПроверитьВложеннуюТранзакцию(ТранзакцияАктивнаНаНачалоВыполнения, НазваниеОбработчика)
|
||
|
||
ИмяСобытия = СобытиеЖурналаРегистрации() + "." + НСтр("ru = 'Выполнение обработчиков'", ОбщегоНазначения.КодОсновногоЯзыка());
|
||
Если ТранзакцияАктивнаНаНачалоВыполнения Тогда
|
||
|
||
Если ТранзакцияАктивна() Тогда
|
||
// Проверка поглощенных исключений в обработчиках.
|
||
Попытка
|
||
Константы.ИспользоватьРазделениеПоОбластямДанных.Получить();
|
||
Исключение
|
||
ШаблонКомментария = НСтр("ru = 'Ошибка выполнения обработчика обновления %1:
|
||
|Обработчиком обновления было поглощено исключение при активной внешней транзакции.
|
||
|При активных транзакциях, открытых выше по стеку, исключение также необходимо пробрасывать выше по стеку.'");
|
||
Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонКомментария, НазваниеОбработчика);
|
||
|
||
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
|
||
ВызватьИсключение(Комментарий);
|
||
КонецПопытки;
|
||
Иначе
|
||
ШаблонКомментария = НСтр("ru = 'Ошибка выполнения обработчика обновления %1:
|
||
|Обработчиком обновления была закрыта лишняя транзакция, открытая ранее (выше по стеку).'");
|
||
Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонКомментария, НазваниеОбработчика);
|
||
|
||
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
|
||
ВызватьИсключение(Комментарий);
|
||
КонецЕсли;
|
||
Иначе
|
||
Если ТранзакцияАктивна() Тогда
|
||
ШаблонКомментария = НСтр("ru = 'Ошибка выполнения обработчика обновления %1:
|
||
|Открытая внутри обработчика обновления транзакция осталась активной (не была закрыта или отменена).'");
|
||
Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонКомментария, НазваниеОбработчика);
|
||
|
||
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
|
||
ВызватьИсключение(Комментарий);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ПроверитьСвойстваОбработчиков(ИтерацияОбновления)
|
||
|
||
Для каждого Обработчик Из ИтерацияОбновления.Обработчики Цикл
|
||
ОписаниеОшибки = "";
|
||
|
||
Если ПустаяСтрока(Обработчик.Версия) Тогда
|
||
|
||
Если Обработчик.НачальноеЗаполнение <> Истина Тогда
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'У обработчика не заполнено свойство %1 или свойство %2.'"),
|
||
"Версия", "НачальноеЗаполнение");
|
||
КонецЕсли;
|
||
|
||
ИначеЕсли Обработчик.Версия <> "*"
|
||
И Не СтрНачинаетсяС(Обработчик.Версия, "ОтладкаОбработчика") Тогда
|
||
|
||
Попытка
|
||
НулеваяВерсия = ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Обработчик.Версия, "0.0.0.0") = 0;
|
||
Исключение
|
||
НулеваяВерсия = Ложь;
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'У обработчика неправильно заполнено свойство %1: ""%2"".
|
||
|Правильный формат, например: ""2.1.3.70"".'"),
|
||
"Версия", Обработчик.Версия);
|
||
КонецПопытки;
|
||
|
||
Если НулеваяВерсия Тогда
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'У обработчика неправильно заполнено свойство %1: ""%2"".
|
||
|Версия не может быть нулевой.'"),
|
||
"Версия", Обработчик.Версия);
|
||
КонецЕсли;
|
||
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеОшибки)
|
||
И Обработчик.ВыполнятьВГруппеОбязательных <> Истина
|
||
И Обработчик.Приоритет <> 0 Тогда
|
||
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'У обработчика неправильно заполнено свойство %1 или
|
||
|свойство %2.'"),
|
||
"Приоритет", "ВыполнятьВГруппеОбязательных");
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Если Обработчик.РежимВыполнения <> ""
|
||
И Обработчик.РежимВыполнения <> "Монопольно"
|
||
И Обработчик.РежимВыполнения <> "Оперативно"
|
||
И Обработчик.РежимВыполнения <> "Отложенно" Тогда
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'У обработчика ""%1"" неправильно заполнено свойство %2.
|
||
|Допустимое значение: ""%3"", ""%4"", ""%5"".'"),
|
||
Обработчик.Процедура, "РежимВыполнения", "Монопольно", "Отложенно", "Оперативно");
|
||
КонецЕсли;
|
||
|
||
Если НЕ ЗначениеЗаполнено(ОписаниеОшибки)
|
||
И Обработчик.Опциональный = Истина
|
||
И Обработчик.НачальноеЗаполнение = Истина Тогда
|
||
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'У обработчика не правильно заполнено свойство %1 или
|
||
|свойство %2.'"),
|
||
"Опциональный", "НачальноеЗаполнение");
|
||
КонецЕсли;
|
||
|
||
Если Не ЗначениеЗаполнено(ОписаниеОшибки) Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если ИтерацияОбновления.ЭтоОсновнаяКонфигурация Тогда
|
||
ЗаголовокОшибки = НСтр("ru = 'Ошибка в свойстве обработчика обновления конфигурации'");
|
||
Иначе
|
||
ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Ошибка в свойстве обработчика обновления библиотеки %1 версии %2'"),
|
||
ИтерацияОбновления.Подсистема,
|
||
ИтерацияОбновления.Версия);
|
||
КонецЕсли;
|
||
|
||
ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
ЗаголовокОшибки + Символы.ПС
|
||
+ НСтр("ru = '(%1).'") + Символы.ПС
|
||
+ Символы.ПС
|
||
+ ОписаниеОшибки,
|
||
Обработчик.Процедура);
|
||
|
||
ЗаписатьОшибку(ОписаниеОшибки);
|
||
ВызватьИсключение ОписаниеОшибки;
|
||
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция КоличествоОбработчиковНаТекущуюВерсию(ИтерацииОбновления, РежимВыполненияОтложенногоОбновления)
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("РежимВыполненияОтложенногоОбработчика", Перечисления.РежимыВыполненияОтложенныхОбработчиков.Параллельно);
|
||
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения <> &РежимВыполнения";
|
||
КоличествоРазделенныхОбработчиков = Запрос.Выполнить().Выгрузить().Количество();
|
||
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновленияОбщихДанных.ИмяОбработчика КАК ИмяОбработчика
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновленияОбщихДанных КАК ОбработчикиОбновленияОбщихДанных";
|
||
КоличествоНеразделенныхОбработчиков = Запрос.Выполнить().Выгрузить().Количество();
|
||
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения";
|
||
КоличествоОтложенныхОбработчиков = Запрос.Выполнить().Выгрузить().Количество();
|
||
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполненияОтложенногоОбработчика = &РежимВыполненияОтложенногоОбработчика";
|
||
КоличествоПроцедурРегистрации = Запрос.Выполнить().Выгрузить().Количество();
|
||
|
||
КоличествоОбработчиков = КоличествоРазделенныхОбработчиков + КоличествоНеразделенныхОбработчиков + КоличествоПроцедурРегистрации;
|
||
Если РежимВыполненияОтложенногоОбновления = "Монопольно" Тогда
|
||
КоличествоОбработчиков = КоличествоОбработчиков + КоличествоОтложенныхОбработчиков;
|
||
КонецЕсли;
|
||
|
||
Возврат Новый Структура("ВсегоОбработчиков, ВыполненоОбработчиков", КоличествоОбработчиков, 0);
|
||
|
||
КонецФункции
|
||
|
||
Функция ИмяОбъектаМетаданныхПоИмениМенеджера(ИмяМенеджера)
|
||
|
||
Позиция = СтрНайти(ИмяМенеджера, ".");
|
||
Если Позиция = 0 Тогда
|
||
Возврат "ОбщийМодуль." + ИмяМенеджера;
|
||
КонецЕсли;
|
||
ТипМенеджера = Лев(ИмяМенеджера, Позиция - 1);
|
||
|
||
ИменаТипов = Новый Соответствие;
|
||
ИменаТипов.Вставить("Справочники", "Справочник");
|
||
ИменаТипов.Вставить("Документы", "Документ");
|
||
ИменаТипов.Вставить("Обработки", "Обработка");
|
||
ИменаТипов.Вставить("ПланыВидовХарактеристик", "ПланВидовХарактеристик");
|
||
ИменаТипов.Вставить("РегистрыБухгалтерии", "РегистрБухгалтерии");
|
||
ИменаТипов.Вставить("РегистрыНакопления", "РегистрНакопления");
|
||
ИменаТипов.Вставить("РегистрыРасчета", "РегистрРасчета");
|
||
ИменаТипов.Вставить("РегистрыСведений", "РегистрСведений");
|
||
ИменаТипов.Вставить("БизнесПроцессы", "БизнесПроцесс");
|
||
ИменаТипов.Вставить("ЖурналыДокументов", "ЖурналДокументов");
|
||
ИменаТипов.Вставить("Задачи", "Задача");
|
||
ИменаТипов.Вставить("Отчеты", "Отчет");
|
||
ИменаТипов.Вставить("Константы", "Константа");
|
||
ИменаТипов.Вставить("Перечисления", "Перечисление");
|
||
ИменаТипов.Вставить("ПланыВидовРасчета", "ПланВидовРасчета");
|
||
ИменаТипов.Вставить("ПланыОбмена", "ПланОбмена");
|
||
ИменаТипов.Вставить("ПланыСчетов", "ПланСчетов");
|
||
|
||
ИмяТипа = ИменаТипов[ТипМенеджера];
|
||
Если ИмяТипа = Неопределено Тогда
|
||
Возврат ИмяМенеджера;
|
||
КонецЕсли;
|
||
|
||
Возврат ИмяТипа + Сред(ИмяМенеджера, Позиция);
|
||
КонецФункции
|
||
|
||
Процедура ОтметитьОбработчикиНовыхПодсистем(ВсеОбработчики)
|
||
|
||
// Список объектов новых подсистем.
|
||
ОбъектыНовыхПодсистем = Новый Массив;
|
||
Для Каждого ИмяПодсистемы Из СведенияОбОбновленииИнформационнойБазы().НовыеПодсистемы Цикл
|
||
Подсистема = Метаданные.НайтиПоПолномуИмени(ИмяПодсистемы);
|
||
Если Подсистема = Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
Для Каждого ОбъектМетаданных Из Подсистема.Состав Цикл
|
||
ОбъектыНовыхПодсистем.Добавить(ОбъектМетаданных.ПолноеИмя());
|
||
КонецЦикла;
|
||
КонецЦикла;
|
||
|
||
// Определение обработчиков новых подсистем.
|
||
ВсеОбработчики.Колонки.Добавить("ЭтоНоваяПодсистема", Новый ОписаниеТипов("Булево"));
|
||
Для Каждого ОписаниеОбработчика Из ВсеОбработчики Цикл
|
||
Позиция = СтрНайти(ОписаниеОбработчика.Процедура, ".", НаправлениеПоиска.СКонца);
|
||
ИмяМенеджера = Лев(ОписаниеОбработчика.Процедура, Позиция - 1);
|
||
Если ОбъектыНовыхПодсистем.Найти(ИмяОбъектаМетаданныхПоИмениМенеджера(ИмяМенеджера)) <> Неопределено Тогда
|
||
ОписаниеОбработчика.ЭтоНоваяПодсистема = Истина;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхПодчиненному.
|
||
Процедура ПриОтправкеВерсийПодсистем(ЭлементДанных, ОтправкаЭлемента, Знач СозданиеНачальногоОбраза = Ложь)
|
||
|
||
СтандартнаяОбработка = Истина;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ОбновлениеВерсииИБВМоделиСервиса") Тогда
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса");
|
||
МодульОбновлениеИнформационнойБазыСлужебныйВМоделиСервиса.ПриОтправкеВерсийПодсистем(ЭлементДанных, ОтправкаЭлемента,
|
||
СозданиеНачальногоОбраза, СтандартнаяОбработка);
|
||
КонецЕсли;
|
||
|
||
Если Не СтандартнаяОбработка Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить
|
||
ИЛИ ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать Тогда
|
||
|
||
// Стандартную обработку не переопределяем.
|
||
|
||
ИначеЕсли ТипЗнч(ЭлементДанных) = Тип("РегистрСведенийНаборЗаписей.ВерсииПодсистем") Тогда
|
||
|
||
Если Не СозданиеНачальногоОбраза Тогда
|
||
|
||
// Выгрузку регистра выполняем только при создании начального образа.
|
||
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
|
||
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ОтметкаНачалаОбновления()
|
||
|
||
ОписаниеСеанса = Новый Структура;
|
||
ОписаниеСеанса.Вставить("ИмяКомпьютера");
|
||
ОписаниеСеанса.Вставить("ИмяПриложения");
|
||
ОписаниеСеанса.Вставить("НачалоСеанса");
|
||
ОписаниеСеанса.Вставить("НомерСеанса");
|
||
ОписаниеСеанса.Вставить("НомерСоединения");
|
||
ОписаниеСеанса.Вставить("Пользователь");
|
||
ЗаполнитьЗначенияСвойств(ОписаниеСеанса, ПолучитьТекущийСеансИнформационнойБазы());
|
||
Пользователь = ОписаниеСеанса.Пользователь; // ПользовательИнформационнойБазы
|
||
ОписаниеСеанса.Пользователь = Пользователь.Имя;
|
||
ИмяПараметра = "СтандартныеПодсистемы.ОбновлениеВерсииИБ.СеансОбновленияИнформационнойБазы";
|
||
|
||
МожноВыполнятьОбновление = Истина;
|
||
|
||
Блокировка = Новый БлокировкаДанных;
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
ЭлементБлокировки = Блокировка.Добавить("Константа.СведенияОбОбновленииИБ");
|
||
Иначе
|
||
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ПараметрыРаботыПрограммы");
|
||
ЭлементБлокировки.УстановитьЗначение("ИмяПараметра", ИмяПараметра);
|
||
КонецЕсли;
|
||
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
Блокировка.Заблокировать();
|
||
СохраненныеПараметры = СведенияОСеансеОбновления(ИмяПараметра);
|
||
|
||
Если СохраненныеПараметры = Неопределено Тогда
|
||
СеансыСовпадают = Ложь;
|
||
Иначе
|
||
СеансыСовпадают = ДанныеСовпадают(ОписаниеСеанса, СохраненныеПараметры);
|
||
КонецЕсли;
|
||
|
||
Если Не СеансыСовпадают Тогда
|
||
СеансОбновленияАктивен = СеансАктивен(СохраненныеПараметры);
|
||
Если СеансОбновленияАктивен Тогда
|
||
СеансОбновления = СохраненныеПараметры;
|
||
МожноВыполнятьОбновление = Ложь;
|
||
Иначе
|
||
ЗаписатьСведенияОСеансеОбновления(ИмяПараметра, ОписаниеСеанса);
|
||
СеансОбновления = ОписаниеСеанса;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ЗафиксироватьТранзакцию();
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("МожноВыполнятьОбновление", МожноВыполнятьОбновление);
|
||
Результат.Вставить("СеансОбновления", СеансОбновления);
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция СведенияОСеансеОбновления(ИмяПараметра)
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Сведения = СведенияОбОбновленииИнформационнойБазы();
|
||
СеансОбновления = Сведения.СеансОбновления;
|
||
Иначе
|
||
СеансОбновления = СтандартныеПодсистемыСервер.ПараметрРаботыПрограммы(ИмяПараметра);
|
||
КонецЕсли;
|
||
|
||
Возврат СеансОбновления;
|
||
КонецФункции
|
||
|
||
Процедура ЗаписатьСведенияОСеансеОбновления(ИмяПараметра, ОписаниеСеанса)
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Сведения = СведенияОбОбновленииИнформационнойБазы();
|
||
Сведения.СеансОбновления = ОписаниеСеанса;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(Сведения);
|
||
Иначе
|
||
СтандартныеПодсистемыСервер.УстановитьПараметрРаботыПрограммы(ИмяПараметра, ОписаниеСеанса);
|
||
КонецЕсли;
|
||
КонецПроцедуры
|
||
|
||
Функция СеансАктивен(ОписаниеСеанса)
|
||
Если ОписаниеСеанса = Неопределено Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
СеансыИнформационнойБазы = ПолучитьСеансыИнформационнойБазы();
|
||
|
||
Для Каждого Сеанс Из СеансыИнформационнойБазы Цикл
|
||
Совпадают = ДанныеСовпадают(ОписаниеСеанса, Сеанс);
|
||
Если Совпадают Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат Совпадают;
|
||
КонецФункции
|
||
|
||
Функция ДанныеСовпадают(Данные1, Данные2)
|
||
|
||
Совпадают = Истина;
|
||
Для Каждого КлючИЗначение Из Данные1 Цикл
|
||
Если КлючИЗначение.Ключ = "Пользователь" Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Если Данные2[КлючИЗначение.Ключ] <> КлючИЗначение.Значение Тогда
|
||
Совпадают = Ложь;
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат Совпадают;
|
||
|
||
КонецФункции
|
||
|
||
Функция НоваяТаблицаИнформацииОбОбработчиках() Экспорт
|
||
|
||
ИнфоОбработчиков = Новый ТаблицаЗначений;
|
||
ИнфоОбработчиков.Колонки.Добавить("ИмяОбработчика", Новый ОписаниеТипов("Строка"));
|
||
ИнфоОбработчиков.Колонки.Добавить("РежимВыполнения", Новый ОписаниеТипов("Строка"));
|
||
ИнфоОбработчиков.Колонки.Добавить("ИмяБиблиотеки", Новый ОписаниеТипов("Строка"));
|
||
ИнфоОбработчиков.Колонки.Добавить("Версия", Новый ОписаниеТипов("Строка"));
|
||
ИнфоОбработчиков.Колонки.Добавить("Статус", Новый ОписаниеТипов("Строка"));
|
||
ИнфоОбработчиков.Колонки.Добавить("ДлительностьОбработки", Новый ОписаниеТипов("Число"));
|
||
ИнфоОбработчиков.Колонки.Добавить("ИнформацияОбОшибке", Новый ОписаниеТипов("Строка"));
|
||
ИнфоОбработчиков.Колонки.Добавить("ОбластьДанных", Новый ОписаниеТипов("Число"));
|
||
|
||
Возврат ИнфоОбработчиков;
|
||
|
||
КонецФункции
|
||
|
||
Функция НовыйПрогрессОбновленияОбластейДанных() Экспорт
|
||
|
||
Прогресс = Новый Структура;
|
||
Прогресс.Вставить("Обновлено", 0);
|
||
Прогресс.Вставить("Выполняется", 0);
|
||
Прогресс.Вставить("Ожидают", 0);
|
||
Прогресс.Вставить("Проблемы", 0);
|
||
|
||
Прогресс.Вставить("ОбластиОбновлено", Новый Массив);
|
||
Прогресс.Вставить("ОбластиВыполняется", Новый Массив);
|
||
Прогресс.Вставить("ОбластиОжидает", Новый Массив);
|
||
Прогресс.Вставить("ОбластиСПроблемами", Новый Массив);
|
||
|
||
Возврат Прогресс;
|
||
|
||
КонецФункции
|
||
|
||
Функция ИменаПоЗначениямПеречисления(МетаданныеПеречисления) Экспорт
|
||
|
||
МенеджерПеречисления = Перечисления[МетаданныеПеречисления.Имя];
|
||
Результат = Новый Соответствие;
|
||
Для Каждого ЭлементКоллекции Из МетаданныеПеречисления.ЗначенияПеречисления Цикл // ОбъектМетаданных
|
||
Результат.Вставить(МенеджерПеречисления[ЭлементКоллекции.Имя], ЭлементКоллекции.Имя);
|
||
КонецЦикла;
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Функция ЗначениеПеречисленияПоИмени(ИмяЗначения, МетаданныеПеречисления) Экспорт
|
||
|
||
МенеджерПеречисления = Перечисления[МетаданныеПеречисления.Имя];
|
||
Если Не ЗначениеЗаполнено(ИмяЗначения) Тогда
|
||
Возврат МенеджерПеречисления.ПустаяСсылка();
|
||
КонецЕсли;
|
||
|
||
Результат = Неопределено;
|
||
ДоступныеЗначения = Новый Массив;
|
||
|
||
ИмяЗначенияДляСравнения = ВРег(ИмяЗначения);
|
||
Для Каждого ЭлементКоллекции Из МетаданныеПеречисления.ЗначенияПеречисления Цикл // ОбъектМетаданных
|
||
Если ВРег(ЭлементКоллекции.Имя) = ИмяЗначенияДляСравнения Тогда
|
||
Результат = МенеджерПеречисления[ЭлементКоллекции.Имя];
|
||
Прервать;
|
||
КонецЕсли;
|
||
ДоступныеЗначения.Добавить("""" + ЭлементКоллекции.Имя + """");
|
||
КонецЦикла;
|
||
|
||
Если Результат = Неопределено Тогда
|
||
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'Некорректное имя ""%1"" значения перечисления ""%2"".
|
||
|Доступные значения: %3'"), ИмяЗначения, МетаданныеПеречисления, СтрСоединить(ДоступныеЗначения, ", "));
|
||
КонецЕсли;
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Протоколирование хода обновления.
|
||
|
||
Процедура ЗаписатьИнформацию(Знач Текст) Экспорт
|
||
|
||
ЖурналРегистрации.ДобавитьСообщениеДляЖурналаРегистрации(СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Информация,,, Текст);
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ЗаписатьОшибку(Знач Текст) Экспорт
|
||
|
||
ЖурналРегистрации.ДобавитьСообщениеДляЖурналаРегистрации(СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Ошибка,,, Текст);
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ЗаписатьПредупреждение(Знач Текст) Экспорт
|
||
|
||
ЖурналРегистрации.ДобавитьСообщениеДляЖурналаРегистрации(СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Предупреждение,,, Текст);
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ЗаписатьИнформациюОХодеОбновления(Обработчик, ХодВыполненияОбработчиков, ВФоне)
|
||
|
||
Если ХодВыполненияОбработчиков = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
ХодВыполненияОбработчиков.ВыполненоОбработчиков = ХодВыполненияОбработчиков.ВыполненоОбработчиков + 1;
|
||
|
||
Если Не ОбщегоНазначения.РазделениеВключено() Тогда
|
||
Сообщение = НСтр("ru = 'Выполняется обработчик обновления %1 (%2 из %3).'");
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
Сообщение, Обработчик.Процедура,
|
||
ХодВыполненияОбработчиков.ВыполненоОбработчиков, ХодВыполненияОбработчиков.ВсегоОбработчиков);
|
||
ЗаписатьИнформацию(Сообщение);
|
||
КонецЕсли;
|
||
|
||
Если ВФоне Тогда
|
||
Прогресс = 10 + ХодВыполненияОбработчиков.ВыполненоОбработчиков / ХодВыполненияОбработчиков.ВсегоОбработчиков * 90;
|
||
ДлительныеОперации.СообщитьПрогресс(Прогресс);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Описание обновлений
|
||
|
||
// Вывести описания изменений в указанной версии.
|
||
//
|
||
// Параметры:
|
||
// НомерВерсии - Строка - номер версии, для которого выводится описание из макета
|
||
// табличного документа МакетОписаниеОбновлений в табличный документ.
|
||
// ДокументОписаниеОбновлений.
|
||
//
|
||
Процедура ВывестиОписаниеИзменений(Знач НомерВерсии, ДокументОписаниеОбновлений, МакетОписаниеОбновлений)
|
||
|
||
Номер = СтрЗаменить(НомерВерсии, ".", "_");
|
||
|
||
Если МакетОписаниеОбновлений.Области.Найти("Шапка" + Номер) = Неопределено Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
ДокументОписаниеОбновлений.Вывести(МакетОписаниеОбновлений.ПолучитьОбласть("Шапка" + Номер));
|
||
ДокументОписаниеОбновлений.НачатьГруппуСтрок("Версия" + Номер);
|
||
ДокументОписаниеОбновлений.Вывести(МакетОписаниеОбновлений.ПолучитьОбласть("Версия" + Номер));
|
||
ДокументОписаниеОбновлений.ЗакончитьГруппуСтрок();
|
||
ДокументОписаниеОбновлений.Вывести(МакетОписаниеОбновлений.ПолучитьОбласть("Отступ"));
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПоследняяВерсияОтображенияИзмененийСистемы(Знач ИмяПользователя = Неопределено) Экспорт
|
||
|
||
Если ИмяПользователя = Неопределено Тогда
|
||
ИмяПользователя = ИмяПользователя();
|
||
КонецЕсли;
|
||
|
||
ПоследняяВерсия = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("ОбновлениеИБ",
|
||
"ПоследняяВерсияОтображенияИзмененийСистемы", , , ИмяПользователя);
|
||
|
||
Возврат ПоследняяВерсия;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ОпределитьВыводОписанияОбновлений(ВыводитьОписаниеОбновлений)
|
||
|
||
Если ВыводитьОписаниеОбновлений И Не ОбщегоНазначения.РазделениеВключено() Тогда
|
||
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить("ОбновлениеИБ", "ВывестиОписаниеИзмененийДляАдминистратора", Истина, , ИмяПользователя());
|
||
КонецЕсли;
|
||
|
||
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
СведенияОбОбновленииИБ = СведенияОбОбновленииИнформационнойБазы();
|
||
СведенияОбОбновленииИБ.ВыводитьОписаниеОбновлений = ВыводитьОписаниеОбновлений;
|
||
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновленииИБ);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Возвращает список разделов описания изменений системы.
|
||
//
|
||
// Возвращаемое значение:
|
||
// СписокЗначений:
|
||
// * Значение - Число - вес версии.
|
||
// * Представление - Строка - версии.
|
||
//
|
||
Функция РазделыОписанияИзменений() Экспорт
|
||
|
||
Разделы = Новый СписокЗначений;
|
||
ВесВерсииМетаданных = ВесВерсии(Метаданные.Версия);
|
||
|
||
МакетОписаниеОбновлений = Метаданные.ОбщиеМакеты.Найти("ОписаниеИзмененийСистемы");
|
||
Если МакетОписаниеОбновлений <> Неопределено Тогда
|
||
ПредикатВерсии = "Версия";
|
||
ПредикатШапки = "Шапка";
|
||
Макет = ПолучитьОбщийМакет(МакетОписаниеОбновлений);
|
||
|
||
Для каждого Область Из Макет.Области Цикл
|
||
Если СтрНайти(Область.Имя, ПредикатВерсии) = 0 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ВерсияВФорматеОписания = Сред(Область.Имя, СтрДлина(ПредикатВерсии) + 1);
|
||
|
||
Если Макет.Области.Найти(ПредикатШапки + ВерсияВФорматеОписания) = Неопределено Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
РазрядыВерсииСтроками = СтрРазделить(ВерсияВФорматеОписания, "_");
|
||
Если РазрядыВерсииСтроками.Количество() <> 4 Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
ВесВерсии = ВесВерсииИзМассиваСтрок(РазрядыВерсииСтроками);
|
||
|
||
Версия = ""
|
||
+ Число(РазрядыВерсииСтроками[0]) + "."
|
||
+ Число(РазрядыВерсииСтроками[1]) + "."
|
||
+ Число(РазрядыВерсииСтроками[2]) + "."
|
||
+ Число(РазрядыВерсииСтроками[3]);
|
||
|
||
Если ВесВерсии > ВесВерсииМетаданных Тогда
|
||
ТекстИсключения = НСтр("ru = 'В общем макете %1 для одного из разделов изменений
|
||
|установлена версия выше, чем в метаданных. (%2, должна быть %3)'");
|
||
ТекстИсключения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения,
|
||
"ОписаниеИзмененийСистемы", Версия, Метаданные.Версия);
|
||
ВызватьИсключение ТекстИсключения;
|
||
КонецЕсли;
|
||
|
||
Разделы.Добавить(ВесВерсии, Версия);
|
||
КонецЦикла;
|
||
|
||
Разделы.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
|
||
КонецЕсли;
|
||
|
||
|
||
Возврат Разделы;
|
||
|
||
КонецФункции
|
||
|
||
Функция ВесВерсииИзМассиваСтрок(РазрядыВерсииСтроками)
|
||
|
||
Возврат 0
|
||
+ Число(РазрядыВерсииСтроками[0]) * 1000000000
|
||
+ Число(РазрядыВерсииСтроками[1]) * 1000000
|
||
+ Число(РазрядыВерсииСтроками[2]) * 1000
|
||
+ Число(РазрядыВерсииСтроками[3]);
|
||
|
||
КонецФункции
|
||
|
||
Функция ПолучитьВерсииБольшеЗаданной(Разделы, Версия)
|
||
|
||
Результат = Новый Массив;
|
||
|
||
Если Разделы = Неопределено Тогда
|
||
Разделы = РазделыОписанияИзменений();
|
||
КонецЕсли;
|
||
|
||
ВесВерсии = ВесВерсии(Версия);
|
||
Для каждого ЭлементСписка Из Разделы Цикл
|
||
Если ЭлементСписка.Значение <= ВесВерсии Тогда
|
||
Продолжить;
|
||
КонецЕсли;
|
||
|
||
Результат.Добавить(ЭлементСписка.Представление);
|
||
КонецЦикла;
|
||
|
||
Возврат Результат;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ОтключитьОтложенноеОбновление()
|
||
|
||
ПриВключенииОтложенногоОбновления(Ложь);
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ВыполненыВсеОтложенныеОбработчики(СведенияОбОбновлении)
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.Статус КАК Статус
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.Статус <> &Статус";
|
||
НевыполненныеОбработчики = Запрос.Выполнить().Выгрузить();
|
||
|
||
Если НевыполненныеОбработчики.Количество() = 0 Тогда
|
||
СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления = ТекущаяДатаСеанса();
|
||
СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно = Истина;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
Константы.ОтложенноеОбновлениеЗавершеноУспешно.Установить(Истина);
|
||
Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
|
||
Константы.ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.Установить(Истина);
|
||
КонецЕсли;
|
||
|
||
Возврат Истина;
|
||
Иначе
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Вспомогательные процедуры и функции отложенного обновления.
|
||
|
||
Процедура ОбработчикПроверкиВеденияУчета(Проверка, ПараметрыПроверки) Экспорт
|
||
|
||
// Обработка не требуется, регистрация проблемных объектов выполняется
|
||
// из обработчиков обновления.
|
||
Возврат;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция КоличествоПроблемСДанными() Экспорт
|
||
|
||
Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
|
||
Возврат 0;
|
||
КонецЕсли;
|
||
|
||
МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
|
||
Проверка = МодульКонтрольВеденияУчета.ПроверкаПоИдентификатору("ОбновлениеИнформационнойБазыПроблемаСДанными");
|
||
КоличествоПроблем = МодульКонтрольВеденияУчета.КоличествоПроблемПоПравилуПроверки(Проверка);
|
||
|
||
Возврат КоличествоПроблем;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ОчиститьЗарегистрированныеПроблемыСДанными()
|
||
|
||
Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтрольВеденияУчета") Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
МодульКонтрольВеденияУчета = ОбщегоНазначения.ОбщийМодуль("КонтрольВеденияУчета");
|
||
|
||
Проверка = МодульКонтрольВеденияУчета.ПроверкаПоИдентификатору("ОбновлениеИнформационнойБазыПроблемаСДанными");
|
||
МодульКонтрольВеденияУчета.ОчиститьРезультатПоПроверке(Проверка);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Только для внутреннего использования.
|
||
//
|
||
Функция ВыполнитьОтложенныйОбработчикОбновления(ПараметрыОбновления = Неопределено)
|
||
|
||
КонтекстОбработчика = НовыйКонтекстОбработчика();
|
||
ОбработчикОбновления = НайтиОбработчикОбновления(КонтекстОбработчика, ПараметрыОбновления);
|
||
|
||
Если ТипЗнч(ОбработчикОбновления) = Тип("СтрокаТаблицыЗначений") Тогда
|
||
АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено);
|
||
|
||
Попытка
|
||
ОбработчикВыполнилсяБезОшибок = Ложь;
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ДополнитьКонтекстМногопоточногоОбработчика(КонтекстОбработчика);
|
||
ОбрабатываемыеДанные = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
ОбрабатываемыеДанные.ПоследняяВыбраннаяЗапись = Неопределено;
|
||
ОбрабатываемыеДанные.ПоискЗавершен = Ложь;
|
||
ПараметрыВыборки = ОбрабатываемыеДанные.ПараметрыВыборки;
|
||
ПроверитьПараметрыВыборки(ПараметрыВыборки);
|
||
ПараметрыВыборки.МаксимумВыборки = ОбновлениеИнформационнойБазы.МаксимальноеКоличествоЗаписейВВыборке();
|
||
ПараметрыПоиска = НовыеПараметрыПоискаПорции();
|
||
ПараметрыПоиска.ПараметрыВыборки = ПараметрыВыборки;
|
||
ПараметрыПоиска.ПоследняяВыбраннаяЗапись = ОбрабатываемыеДанные.ПоследняяВыбраннаяЗапись;
|
||
ПараметрыОбхода = ПараметрыОбходаДанныхДляОбновления(ПараметрыПоиска);
|
||
Очередь = КонтекстОбработчика.Параметры.Очередь;
|
||
ИтераторОбхода = ТекущиеПараметрыОбхода(ПараметрыОбхода);
|
||
ДополнительныеИсточникиДанных = ПараметрыВыборки.ДополнительныеИсточникиДанных;
|
||
|
||
Пока ИтераторОбхода <> Неопределено Цикл
|
||
ОбработчикВыполнилсяБезОшибок = Ложь;
|
||
СсылочныйОбъект = ИтераторОбхода.СсылочныйОбъект;
|
||
ТабличныйОбъект = ИтераторОбхода.ТабличныйОбъект;
|
||
НаборДанных = НовыйНаборДанныхДляОбновления();
|
||
ЗаписьДанных = НаборДанных.Добавить();
|
||
ПараметрыВыборки.ДополнительныеИсточникиДанных = ОбновлениеИнформационнойБазы.ИсточникиДанных(
|
||
ДополнительныеИсточникиДанных,
|
||
СсылочныйОбъект,
|
||
ТабличныйОбъект);
|
||
ЗаписьДанных.Данные = ВыбратьДанныеПорции(ПараметрыВыборки, Очередь, СсылочныйОбъект, ТабличныйОбъект);
|
||
ЗаписьДанных.СсылочныйОбъект = СсылочныйОбъект;
|
||
ЗаписьДанных.ТабличныйОбъект = ТабличныйОбъект;
|
||
ОбновляемыеДанные = НоваяПорцияДляОбновления();
|
||
ОбновляемыеДанные.НаборДанных = НаборДанных;
|
||
|
||
Если ЗаписьДанных.Данные.Количество() > 0 Тогда
|
||
ОбновляемыеДанные.ПерваяЗапись = КлючЗаписиПервойСтрокиНабораДанных(НаборДанных);
|
||
ОбновляемыеДанные.ПоследняяЗапись = КлючЗаписиПоследнейСтрокиНабораДанных(НаборДанных);
|
||
КонецЕсли;
|
||
|
||
КонтекстОбработчика.Параметры.ОбновляемыеДанные = ОбновляемыеДанные;
|
||
Количество = ЗаписьДанных.Данные.Количество();
|
||
Если КонтекстОбработчика.ВыполнитьОбработчик Тогда
|
||
ВыполнитьОтложенныйОбработчик(КонтекстОбработчика, АдресРезультата);
|
||
КонецЕсли;
|
||
ОбработчикВыполнилсяБезОшибок = Истина;
|
||
ЗавершитьВыполнениеОтложенногоОбработчика(КонтекстОбработчика, АдресРезультата);
|
||
|
||
Если Количество > 0 Тогда
|
||
ОбрабатываемыеДанные.ПоследняяВыбраннаяЗапись = КлючЗаписиПоследнейСтрокиНабораДанных(НаборДанных);
|
||
Иначе
|
||
ОбрабатываемыеДанные.ПоследняяВыбраннаяЗапись = Неопределено;
|
||
КонецЕсли;
|
||
|
||
СледующиеПараметрыОбхода(ПараметрыОбхода, Количество = ПараметрыВыборки.МаксимумВыборки);
|
||
ИтераторОбхода = ТекущиеПараметрыОбхода(ПараметрыОбхода);
|
||
КонецЦикла;
|
||
|
||
ПараметрыВыборки.ДополнительныеИсточникиДанных = ДополнительныеИсточникиДанных;
|
||
Иначе
|
||
Если КонтекстОбработчика.ВыполнитьОбработчик Тогда
|
||
ВыполнитьОтложенныйОбработчик(КонтекстОбработчика, АдресРезультата);
|
||
КонецЕсли;
|
||
ОбработчикВыполнилсяБезОшибок = Истина;
|
||
ЗавершитьВыполнениеОтложенногоОбработчика(КонтекстОбработчика, АдресРезультата);
|
||
КонецЕсли;
|
||
Исключение
|
||
ОбработатьИсключениеОбработчика(КонтекстОбработчика, ОбработчикОбновления, ИнформацияОбОшибке());
|
||
// Если обработчик вызвал исключение, то вызываем процедуру завершения обработчика.
|
||
Если Не ОбработчикВыполнилсяБезОшибок Тогда
|
||
КонтекстОбработчика.Вставить("ОбработкаИсключенияОбработчика");
|
||
ЗавершитьВыполнениеОтложенногоОбработчика(КонтекстОбработчика, АдресРезультата);
|
||
КонецЕсли;
|
||
КонецПопытки;
|
||
ИначеЕсли ОбработчикОбновления = Ложь Тогда
|
||
Возврат Ложь;
|
||
КонецЕсли;
|
||
|
||
Возврат Истина;
|
||
|
||
КонецФункции
|
||
|
||
// Завершить выполнение отложенного обработчика в основном потоке, после завершения работы фонового задания.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
//
|
||
Процедура ЗавершитьВыполнениеОтложенногоОбработчикаОбновления(КонтекстОбработчика)
|
||
|
||
ПараллельныйРежим = КонтекстОбработчика.ПараллельныйРежим;
|
||
ТекущаяИтерацияОбновления = КонтекстОбработчика.ТекущаяИтерацияОбновления;
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(КонтекстОбработчика.ИмяОбработчика);
|
||
УстанавливаемыеСвойства = Новый Структура;
|
||
|
||
Если ОбработчикОбновления.Статус = Перечисления.СтатусыОбработчиковОбновления.Выполнен Тогда
|
||
|
||
СведенияОБлокируемыхОбъектах = СведенияОБлокируемыхОбъектах();
|
||
СведенияОбОбработчике = СведенияОБлокируемыхОбъектах.Обработчики[ОбработчикОбновления.ИмяОбработчика];
|
||
Если СведенияОбОбработчике <> Неопределено Тогда
|
||
СведенияОбОбработчике.Выполнен = Истина;
|
||
ЗаписатьСведенияОБлокируемыхОбъектах(СведенияОБлокируемыхОбъектах);
|
||
КонецЕсли;
|
||
УстанавливаемыеСвойства.Вставить("ИнформацияОбОшибке", "");
|
||
|
||
ИначеЕсли ОбработчикОбновления.Статус = Перечисления.СтатусыОбработчиковОбновления.Выполняется Тогда
|
||
|
||
// Если у обработчика стоит высокий приоритет,
|
||
// то он вызывается пять раз, после чего вызывается следующий обработчик.
|
||
ЗапускиСПриоритетом = Неопределено;
|
||
Если ОбработчикОбновления.Приоритет = "ЖелательноБыстрее" Тогда
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
ЗапускиСПриоритетом = СтатистикаВыполнения["ЗапускиСПриоритетом"];
|
||
ЗапускиСПриоритетом = ?(ЗапускиСПриоритетом = Неопределено, 1, ?(ЗапускиСПриоритетом = 4, 0, ЗапускиСПриоритетом + 1));
|
||
СтатистикаВыполнения.Вставить("ЗапускиСПриоритетом", ЗапускиСПриоритетом);
|
||
УстанавливаемыеСвойства.Вставить("СтатистикаВыполнения", Новый ХранилищеЗначения(СтатистикаВыполнения));
|
||
КонецЕсли;
|
||
|
||
Если ЗапускиСПриоритетом = Неопределено Или ЗапускиСПриоритетом = 0 Тогда
|
||
УстанавливаемыеСвойства.Вставить("ИтерацияЗапуска", ТекущаяИтерацияОбновления);
|
||
КонецЕсли;
|
||
|
||
Иначе
|
||
УстанавливаемыеСвойства.Вставить("ИтерацияЗапуска", ТекущаяИтерацияОбновления);
|
||
КонецЕсли;
|
||
|
||
УстановитьСвойстваОбработчика(ОбработчикОбновления.ИмяОбработчика, УстанавливаемыеСвойства);
|
||
|
||
// В параллельном режиме обновление нужно останавливать, если обработчик не удалось выполнить,
|
||
// т.к. от данных, которые он обрабатывает, могут зависеть другие обработчики.
|
||
Если ПараллельныйРежим
|
||
И ОбработчикОбновления.Статус = Перечисления.СтатусыОбработчиковОбновления.Ошибка
|
||
И ОбработчикОбновления.ЧислоПопыток >= МаксимумПопытокОбновления(ОбработчикОбновления) Тогда
|
||
СведенияОбОбновлении = СведенияОбОбновленииИнформационнойБазы();
|
||
СведенияОбОбновлении.ВремяОкончаниеОтложенногоОбновления = ТекущаяДатаСеанса();
|
||
СведенияОбОбновлении.ОтложенноеОбновлениеЗавершеноУспешно = Ложь;
|
||
ЗаписатьСведенияОбОбновленииИнформационнойБазы(СведенияОбОбновлении);
|
||
Константы.ОтложенноеОбновлениеЗавершеноУспешно.Установить(Ложь);
|
||
Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ() Тогда
|
||
Константы.ОтложенноеОбновлениеВГлавномУзлеЗавершеноУспешно.Установить(Ложь);
|
||
КонецЕсли;
|
||
|
||
ШаблонОшибки = НСтр("ru = 'Не удалось выполнить обработчик обновления ""%1"". Подробнее в журнале регистрации.'");
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОшибки,
|
||
КонтекстОбработчика.ИмяОбработчика);
|
||
КонтекстОбработчика.Вставить("ОшибкаПриЗавершенииОбработчика", ТекстОшибки);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция ПереданныеПараметрыОбработчикаОбновления(Параметры)
|
||
ПереданныеПараметры = Новый Структура;
|
||
Для Каждого Параметр Из Параметры Цикл
|
||
Если Параметр.Ключ <> "ОбработкаЗавершена"
|
||
И Параметр.Ключ <> "ПрогрессВыполнения"
|
||
И Параметр.Ключ <> "Очередь"
|
||
И Параметр.Ключ <> "ОбновляемыеДанные" Тогда
|
||
ПереданныеПараметры.Вставить(Параметр.Ключ, Параметр.Значение);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат ПереданныеПараметры;
|
||
КонецФункции
|
||
|
||
Функция НовыеСведенияОбОбновлении(СтарыеСведения = Неопределено)
|
||
|
||
СведенияОбОбновлении = Новый Структура;
|
||
СведенияОбОбновлении.Вставить("ВремяНачалаОбновления");
|
||
СведенияОбОбновлении.Вставить("ВремяОкончанияОбновления");
|
||
СведенияОбОбновлении.Вставить("ПродолжительностьОбновления");
|
||
СведенияОбОбновлении.Вставить("ВремяНачалаОтложенногоОбновления");
|
||
СведенияОбОбновлении.Вставить("ВремяОкончаниеОтложенногоОбновления");
|
||
СведенияОбОбновлении.Вставить("НомерСеанса", Новый СписокЗначений());
|
||
СведенияОбОбновлении.Вставить("ОтложенноеОбновлениеЗавершеноУспешно");
|
||
СведенияОбОбновлении.Вставить("ДеревоОбработчиков", Новый ДеревоЗначений());
|
||
СведенияОбОбновлении.Вставить("ВерсияДереваОбработчиков", "");
|
||
СведенияОбОбновлении.Вставить("ВыводитьОписаниеОбновлений", Ложь);
|
||
СведенияОбОбновлении.Вставить("ЛегальнаяВерсия", "");
|
||
СведенияОбОбновлении.Вставить("НовыеПодсистемы", Новый Массив);
|
||
СведенияОбОбновлении.Вставить("ВсеНовыеПодсистемы", Новый Массив);
|
||
СведенияОбОбновлении.Вставить("УправлениеОтложеннымОбновлением", Новый Структура);
|
||
СведенияОбОбновлении.Вставить("ТекущаяИтерацияОбновления", 1);
|
||
СведенияОбОбновлении.Вставить("СеансОбновления");
|
||
СведенияОбОбновлении.Вставить("ВерсияУдалениеПатчей");
|
||
СведенияОбОбновлении.Вставить("ЗависимостьГруппОбработчиков", Новый Соответствие);
|
||
СведенияОбОбновлении.Вставить("ВерсииПодсистемНаНачалоОбновления", Новый Соответствие);
|
||
СведенияОбОбновлении.Вставить("ДатаНачалаСеансаОбновления", Неопределено);
|
||
|
||
Если ТипЗнч(СтарыеСведения) = Тип("Структура") Тогда
|
||
ЗаполнитьЗначенияСвойств(СведенияОбОбновлении, СтарыеСведения);
|
||
КонецЕсли;
|
||
|
||
Возврат СведенияОбОбновлении;
|
||
|
||
КонецФункции
|
||
|
||
Функция РежимВыполненияОтложенногоОбновления(ПараметрыОбновления)
|
||
|
||
ИнформационнаяБазаФайловая = ОбщегоНазначения.ИнформационнаяБазаФайловая();
|
||
РазделениеВключено = ОбщегоНазначения.РазделениеВключено();
|
||
ДоступноИспользованиеРазделенныхДанных = ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных();
|
||
ВыполнятьОтложенныеОбработчики = ПараметрыОбновления.ВыполнятьОтложенныеОбработчики;
|
||
ПараметрЗапускаКлиента = ПараметрыСеанса.ПараметрыКлиентаНаСервере.Получить("ПараметрЗапуска");
|
||
|
||
Если Не РазделениеВключено Или ДоступноИспользованиеРазделенныхДанных Тогда
|
||
Если ИнформационнаяБазаФайловая
|
||
Или СтрНайти(НРег(ПараметрЗапускаКлиента), НРег("ВыполнитьОтложенноеОбновлениеСейчас")) > 0
|
||
Или ВыполнятьОтложенныеОбработчики Тогда
|
||
Возврат "Монопольно";
|
||
Иначе
|
||
Возврат "Отложенно";
|
||
КонецЕсли;
|
||
Иначе
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
КонецФункции
|
||
|
||
// Получает сведения об обновлении информационной базы из константы "СведенияОбОбновленииИБ".
|
||
//
|
||
Функция СведенияОБлокируемыхОбъектах() Экспорт
|
||
|
||
УстановитьПривилегированныйРежим(Истина);
|
||
|
||
Если ОбщегоНазначения.РазделениеВключено()
|
||
И Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
|
||
Возврат НовыеСведенияОБлокируемыхОбъектах();
|
||
КонецЕсли;
|
||
|
||
СведенияОБлокируемыхОбъектах = Константы.СведенияОБлокируемыхОбъектах.Получить().Получить();
|
||
Если ТипЗнч(СведенияОБлокируемыхОбъектах) <> Тип("Структура") Тогда
|
||
Возврат НовыеСведенияОБлокируемыхОбъектах();
|
||
КонецЕсли;
|
||
|
||
СведенияОБлокируемыхОбъектах = НовыеСведенияОБлокируемыхОбъектах(СведенияОБлокируемыхОбъектах);
|
||
Возврат СведенияОБлокируемыхОбъектах;
|
||
|
||
КонецФункции
|
||
|
||
// Подготовка запуска обработчика обновления в основном потоке.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// ОбработчикОбновления - СтрокаДереваЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
// ПараметрыОбновления - см. ВыполнитьОбновлениеИнформационнойБазы
|
||
// СведенияОбОбновлении - см. СведенияОбОбновленииИнформационнойБазы
|
||
//
|
||
Процедура ПередЗапускомПроцедурыОбработкиДанных(КонтекстОбработчика,
|
||
ОбработчикОбновления,
|
||
ПараметрыОбновления,
|
||
СведенияОбОбновлении)
|
||
|
||
КонтекстОбработчика.ЗаписыватьВЖурнал = Константы.ДетализироватьОбновлениеИБВЖурналеРегистрации.Получить();
|
||
КонтекстОбработчика.ТранзакцияАктивнаНаНачалоВыполнения = ТранзакцияАктивна();
|
||
|
||
Попытка
|
||
ИмяОбработчика = ОбработчикОбновления.ИмяОбработчика;
|
||
ВерсииПодсистемНаНачалоОбновления = СведенияОбОбновлении.ВерсииПодсистемНаНачалоОбновления;
|
||
ВерсияПодсистемыНаНачалоОбновления = ВерсииПодсистемНаНачалоОбновления[ОбработчикОбновления.ИмяБиблиотеки];
|
||
|
||
КонтекстОбработчика.ЗапускВыполненБезОшибок = Истина;
|
||
СообщениеОЗапущенномОбработчике = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Выполняется процедура обновления ""%1"".'"), ИмяОбработчика);
|
||
ЖурналРегистрации.ДобавитьСообщениеДляЖурналаРегистрации(СобытиеЖурналаРегистрации(),
|
||
УровеньЖурналаРегистрации.Информация,,, СообщениеОЗапущенномОбработчике);
|
||
|
||
// Прогресс выполнения процедуры обработки данных.
|
||
ПрогрессВыполнения = Новый Структура;
|
||
ПрогрессВыполнения.Вставить("ВсегоОбъектов", 0);
|
||
ПрогрессВыполнения.Вставить("ОбработаноОбъектов", 0);
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
Если СтатистикаВыполнения["ПрогрессВыполнения"] <> Неопределено
|
||
И ТипЗнч(СтатистикаВыполнения["ПрогрессВыполнения"]) = Тип("Структура") Тогда
|
||
ЗаполнитьЗначенияСвойств(ПрогрессВыполнения, СтатистикаВыполнения["ПрогрессВыполнения"]);
|
||
КонецЕсли;
|
||
|
||
// Инициализация параметров обработчика.
|
||
Параметры = СтатистикаВыполнения["ПараметрыОбработчика"];
|
||
Если Параметры = Неопределено Тогда
|
||
Параметры = Новый Структура;
|
||
КонецЕсли;
|
||
|
||
КонтекстОбработчика.Параметры = Параметры;
|
||
|
||
Если ПараметрыОбновления.ПараллельныйРежим Тогда
|
||
Параметры.Вставить("ОбработкаЗавершена", Неопределено);
|
||
Иначе
|
||
Параметры.Вставить("ОбработкаЗавершена", Истина);
|
||
КонецЕсли;
|
||
|
||
Параметры.Вставить("ИмяОбработчика", ИмяОбработчика);
|
||
Параметры.Вставить("ПрогрессВыполнения", ПрогрессВыполнения);
|
||
Параметры.Вставить("ВерсияПодсистемыНаНачалоОбновления", ВерсияПодсистемыНаНачалоОбновления);
|
||
|
||
Параметры.Вставить("Очередь", ОбработчикОбновления.ОчередьОтложеннойОбработки);
|
||
|
||
Если КонтекстОбработчика.ЗаписыватьВЖурнал Тогда
|
||
КонтекстОбработчика.ДетальноеОписаниеОбработчика = ПодготовитьДетальнуюИнформациюОХодеОбновления(ОбработчикОбновления,
|
||
Параметры,
|
||
ОбработчикОбновления.ИмяБиблиотеки,
|
||
Истина);
|
||
КонецЕсли;
|
||
|
||
КоличествоЗапусковПроцедурыОбновления = КоличествоЗапусковПроцедурыОбновления(СтатистикаВыполнения);
|
||
ЧислоПотоковОбновления = КоличествоПотоковОбновленияИнформационнойБазы();
|
||
МаксимальноеКоличествоЗапусков = ЧислоПотоковОбновления * 10000;
|
||
|
||
Если КоличествоЗапусковПроцедурыОбновления > МаксимальноеКоличествоЗапусков Тогда // Защита от зацикливания.
|
||
Если ПараметрыОбновления.ПараллельныйРежим
|
||
И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()
|
||
И ПараметрыОбновления.ЕстьОбработчикиГлавногоУзла Тогда
|
||
ТекстОшибки = НСтр("ru = 'Превышено допустимое количество запусков процедуры обновления.
|
||
|Убедитесь, что дополнительные процедуры обработки данных в главном узле
|
||
|полностью завершились, выполните синхронизацию данных и повторно
|
||
|запустите выполнение процедур обработки данных в данном узле.'");
|
||
Иначе
|
||
ТекстОшибки = НСтр("ru = 'Превышено допустимое количество запусков процедуры обновления.
|
||
|Выполнение прервано для предотвращения зацикливания механизма обработки данных.'");
|
||
КонецЕсли;
|
||
|
||
МинимальнаяОчередь = МинимальнаяОчередьОтложеннойОбработки();
|
||
|
||
Если Не ПараметрыОбновления.ПараллельныйРежим
|
||
Или МинимальнаяОчередь = ОбработчикОбновления.ОчередьОтложеннойОбработки Тогда
|
||
ЧислоПопыток = МаксимумПопытокОбновления(ОбработчикОбновления);
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика, "ЧислоПопыток", ЧислоПопыток);
|
||
ВызватьИсключение ТекстОшибки;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
// Запуск отложенного обработчика обновления.
|
||
Если СтатистикаВыполнения["НачалоОбработкиДанных"] = Неопределено Тогда
|
||
СтатистикаВыполнения.Вставить("НачалоОбработкиДанных", ТекущаяДатаСеанса());
|
||
КонецЕсли;
|
||
|
||
Свойства = Новый Структура;
|
||
Свойства.Вставить("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполняется);
|
||
Свойства.Вставить("ОбработкаПорцииЗавершена", Ложь);
|
||
Свойства.Вставить("СтатистикаВыполнения", Новый ХранилищеЗначения(СтатистикаВыполнения));
|
||
УстановитьСвойстваОбработчика(ОбработчикОбновления.ИмяОбработчика, Свойства);
|
||
|
||
КонтекстОбработчика.НачалоОбработкиДанных = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
Если ПараметрыОбновления.ПараллельныйРежим
|
||
И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()
|
||
И ОбработчикОбновления.ЗапускатьТолькоВГлавномУзле Тогда
|
||
// В подчиненном узле РИБ только проверяем, что обрабатываемые обработчиком данные
|
||
// пришли из главного узла и обновляем статус обработчика.
|
||
КонтекстОбработчика.ПропуститьПроверкуОбработанныхДанных = Истина;
|
||
ОписаниеОбрабатываемыхДанных = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
ДанныеОбработчика = ОписаниеОбрабатываемыхДанных.ДанныеОбработчика;
|
||
|
||
Если ДанныеОбработчика.Количество() = 0 Тогда
|
||
Параметры.ОбработкаЗавершена = Истина;
|
||
Иначе
|
||
Для Каждого ОбрабатываемыйОбъект Из ДанныеОбработчика Цикл
|
||
Параметры.ОбработкаЗавершена = ОбновлениеИнформационнойБазы.ОбработкаДанныхЗавершена(
|
||
ОбработчикОбновления.ОчередьОтложеннойОбработки,
|
||
ОбрабатываемыйОбъект.Ключ);
|
||
Если Не Параметры.ОбработкаЗавершена Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
Иначе
|
||
КонтекстОбработчика.ВыполнитьОбработчик = Истина;
|
||
Возврат;
|
||
КонецЕсли;
|
||
Исключение
|
||
ОбработатьИсключениеОбработчика(КонтекстОбработчика, ОбработчикОбновления, ИнформацияОбОшибке());
|
||
КонтекстОбработчика.ЗапускВыполненБезОшибок = Ложь;
|
||
КонецПопытки;
|
||
|
||
ЗавершитьПроцедуруОбработкиДанных(КонтекстОбработчика, ОбработчикОбновления.ИмяОбработчика);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Завершение запуска процедуры обработки данных в основном потоке.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// ИмяОбработчика - Строка
|
||
//
|
||
Процедура ПослеЗапускаПроцедурыОбработкиДанных(КонтекстОбработчика, ИмяОбработчика)
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(ИмяОбработчика);
|
||
Параметры = КонтекстОбработчика.Параметры;
|
||
ПараметрыОбновления = КонтекстОбработчика.ПараметрыОбновления;
|
||
УстанавливаемыеСвойства = Новый Структура;
|
||
|
||
Попытка
|
||
ЗавершениеОбработкиДанных = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||
|
||
Если Параметры.ОбработкаЗавершена = Неопределено Тогда
|
||
ТекстОшибки = НСтр("ru = 'Обработчик обновления не инициализировал параметр %1.
|
||
|Выполнение прервано из-за явной ошибки в коде обработчика.'");
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстОшибки, "ОбработкаЗавершена");
|
||
ВызватьИсключение ТекстОшибки;
|
||
КонецЕсли;
|
||
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
ДобавитьКоличествоЗапусков = Истина;
|
||
Если Параметры.ОбработкаЗавершена
|
||
И Не КонтекстОбработчика.Свойство("ОбработкаИсключенияОбработчика") Тогда
|
||
СтатистикаВыполнения.Вставить("ЗавершениеОбработкиДанных", ТекущаяДатаСеанса());
|
||
|
||
УстанавливаемыеСвойства.Вставить("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
УстанавливаемыеСвойства.Вставить("Приоритет","ВПлановомПорядке");
|
||
|
||
// Запись прогресса обновления.
|
||
Если ПараметрыОбновления.Свойство("ВФоне")
|
||
И ПараметрыОбновления.ВФоне Тогда
|
||
ХодВыполненияОбработчиков = ПараметрыОбновления.ХодВыполненияОбработчиков;
|
||
ХодВыполненияОбработчиков.ВыполненоОбработчиков = ХодВыполненияОбработчиков.ВыполненоОбработчиков + 1;
|
||
Прогресс = 10 + ХодВыполненияОбработчиков.ВыполненоОбработчиков / ХодВыполненияОбработчиков.ВсегоОбработчиков * 90;
|
||
ДлительныеОперации.СообщитьПрогресс(Прогресс);
|
||
КонецЕсли;
|
||
ИначеЕсли ПараметрыОбновления.ПараллельныйРежим И Не КонтекстОбработчика.ПропуститьПроверкуОбработанныхДанных Тогда
|
||
ЕстьОбработанныеОбъекты = ПараметрыСеанса.ПараметрыОбработчикаОбновления.ЕстьОбработанныеОбъекты;
|
||
ОчередьОбработчика = ОбработчикОбновления.ОчередьОтложеннойОбработки;
|
||
|
||
МинимальнаяОчередь = 0;
|
||
Если Не ЕстьОбработанныеОбъекты Тогда
|
||
МинимальнаяОчередь = МинимальнаяОчередьОтложеннойОбработки();
|
||
КонецЕсли;
|
||
|
||
ДобавитьКоличествоЗапусков = (ЕстьОбработанныеОбъекты Или ОчередьОбработчика = МинимальнаяОчередь);
|
||
|
||
Если Не ЕстьОбработанныеОбъекты
|
||
И ОчередьОбработчика = МинимальнаяОчередь Тогда
|
||
ЧислоПопыток = ОбработчикОбновления.ЧислоПопыток;
|
||
МаксимумПопыток = МаксимумПопытокОбновления(ОбработчикОбновления) - 1;
|
||
Если ЧислоПопыток >= МаксимумПопыток Тогда
|
||
ТекстИсключения = НСтр("ru = 'Произошло зацикливание процедуры обработки данных. Выполнение прервано.'");
|
||
ВызватьИсключение ТекстИсключения;
|
||
Иначе
|
||
ДобавляемоеЧислоПопыток = ДобавляемоеЧислоПопыток(ОбработчикОбновления, КонтекстОбработчика);
|
||
УстанавливаемыеСвойства.Вставить("ЧислоПопыток", ЧислоПопыток + ДобавляемоеЧислоПопыток);
|
||
КонецЕсли;
|
||
Иначе
|
||
УстанавливаемыеСвойства.Вставить("ЧислоПопыток", 0);
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
// Сохранение данных по процедуре обработки данных.
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ПрогрессВыполнения = СтатистикаВыполнения["ПрогрессВыполнения"];
|
||
Если ПрогрессВыполнения = Неопределено Тогда
|
||
СтатистикаВыполнения.Вставить("ПрогрессВыполнения", Параметры.ПрогрессВыполнения);
|
||
Иначе
|
||
ОбработаноОбъектов = Параметры.ПрогрессВыполнения.ОбработаноОбъектов;
|
||
ПрогрессВыполнения.ОбработаноОбъектов = ПрогрессВыполнения.ОбработаноОбъектов + ОбработаноОбъектов;
|
||
КонецЕсли;
|
||
Иначе
|
||
СтатистикаВыполнения.Вставить("ПрогрессВыполнения", Параметры.ПрогрессВыполнения);
|
||
КонецЕсли;
|
||
|
||
Если ДобавитьКоличествоЗапусков Тогда
|
||
КоличествоЗапусковПроцедурыОбновления = КоличествоЗапусковПроцедурыОбновления(СтатистикаВыполнения) + 1;
|
||
Иначе
|
||
КоличествоЗапусковПроцедурыОбновления = КоличествоЗапусковПроцедурыОбновления(СтатистикаВыполнения);
|
||
КонецЕсли;
|
||
|
||
ДлительностьВыполнения = ЗавершениеОбработкиДанных - КонтекстОбработчика.НачалоОбработкиДанных;
|
||
Если СтатистикаВыполнения["ДлительностьВыполнения"] <> Неопределено Тогда
|
||
ДлительностьВыполнения = ДлительностьВыполнения + СтатистикаВыполнения["ДлительностьВыполнения"];
|
||
КонецЕсли;
|
||
СтатистикаВыполнения.Вставить("ДлительностьВыполнения", ДлительностьВыполнения);
|
||
СтатистикаВыполнения.Вставить("КоличествоЗапусков", КоличествоЗапусковПроцедурыОбновления);
|
||
|
||
УстанавливаемыеСвойства.Вставить("СтатистикаВыполнения", Новый ХранилищеЗначения(СтатистикаВыполнения));
|
||
УстанавливаемыеСвойства.Вставить("ДлительностьОбработки", ДлительностьВыполнения);
|
||
УстановитьСвойстваОбработчика(ОбработчикОбновления.ИмяОбработчика, УстанавливаемыеСвойства);
|
||
Исключение
|
||
ОбработатьИсключениеОбработчика(КонтекстОбработчика, ОбработчикОбновления, ИнформацияОбОшибке());
|
||
КонецПопытки;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Завершение процедуры обработки данных.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// ИмяОбработчика - Строка
|
||
//
|
||
Процедура ЗавершитьПроцедуруОбработкиДанных(КонтекстОбработчика, ИмяОбработчика)
|
||
|
||
ОбработчикОбновления = ОбработчикОбновления(ИмяОбработчика);
|
||
|
||
Параметры = КонтекстОбработчика.Параметры;
|
||
|
||
// Если обработчик обновления передал параметры, их нужно сохранить.
|
||
ПереданныеПараметры = ПереданныеПараметрыОбработчикаОбновления(Параметры);
|
||
СтатистикаВыполнения = ОбработчикОбновления.СтатистикаВыполнения.Получить();
|
||
СтатистикаВыполнения.Вставить("ПараметрыОбработчика", ПереданныеПараметры);
|
||
УстановитьСвойствоОбработчика(ОбработчикОбновления.ИмяОбработчика,
|
||
"СтатистикаВыполнения",
|
||
Новый ХранилищеЗначения(СтатистикаВыполнения));
|
||
|
||
Если КонтекстОбработчика.ЕстьНеЗакрытыеТранзакции Тогда
|
||
// В случае нахождения вложенной транзакции обработчик обновления повторно не вызывается.
|
||
ОбработчикОбновления.Статус = Перечисления.СтатусыОбработчиковОбновления.Ошибка;
|
||
ОбработчикОбновления.ИнформацияОбОшибке = Строка(ОбработчикОбновления.ИнформацияОбОшибке)
|
||
+ Символы.ПС + КонтекстОбработчика.ИнформацияОбОшибке;
|
||
|
||
ОбработчикОбновления.ЧислоПопыток = МаксимумПопытокОбновления(ОбработчикОбновления);
|
||
|
||
Свойства = Новый Структура;
|
||
Свойства.Вставить("ЧислоПопыток", ОбработчикОбновления.ЧислоПопыток);
|
||
Свойства.Вставить("Статус", ОбработчикОбновления.Статус);
|
||
Свойства.Вставить("ИнформацияОбОшибке", ОбработчикОбновления.ИнформацияОбОшибке);
|
||
УстановитьСвойстваОбработчика(ОбработчикОбновления.ИмяОбработчика, Свойства);
|
||
КонецЕсли;
|
||
|
||
Если КонтекстОбработчика.ЗаписыватьВЖурнал Тогда
|
||
ЗаписатьДетальнуюИнформациюОХодеОбновления(КонтекстОбработчика.ДетальноеОписаниеОбработчика);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ЗаполнитьБлокируемыеОбъекты(СтрокаВерсия, СведенияОБлокируемыхОбъектах)
|
||
|
||
Для Каждого Обработчик Из СтрокаВерсия.Строки Цикл
|
||
ПроцедураПроверки = Обработчик.ПроцедураПроверки;
|
||
БлокируемыеОбъекты = Обработчик.БлокируемыеОбъекты;
|
||
Если ЗначениеЗаполнено(ПроцедураПроверки) И ЗначениеЗаполнено(БлокируемыеОбъекты) Тогда
|
||
СвойстваОбработчика = Новый Структура;
|
||
СвойстваОбработчика.Вставить("Выполнен", Ложь);
|
||
СвойстваОбработчика.Вставить("ПроцедураПроверки", ПроцедураПроверки);
|
||
|
||
СведенияОБлокируемыхОбъектах.Обработчики.Вставить(Обработчик.ИмяОбработчика, СвойстваОбработчика);
|
||
МассивБлокируемыхОбъектов = СтрРазделить(БлокируемыеОбъекты, ",");
|
||
Для Каждого БлокируемыйОбъект Из МассивБлокируемыхОбъектов Цикл
|
||
БлокируемыйОбъект = СтрЗаменить(СокрЛП(БлокируемыйОбъект), ".", "");
|
||
ИнформацияОбОбъекте = СведенияОБлокируемыхОбъектах.БлокируемыеОбъекты[БлокируемыйОбъект];
|
||
Если ИнформацияОбОбъекте = Неопределено Тогда
|
||
МассивОбработчиков = Новый Массив;
|
||
МассивОбработчиков.Добавить(Обработчик.ИмяОбработчика);
|
||
СведенияОБлокируемыхОбъектах.БлокируемыеОбъекты.Вставить(БлокируемыйОбъект, МассивОбработчиков);
|
||
Иначе
|
||
СведенияОБлокируемомОбъекте = СведенияОБлокируемыхОбъектах.БлокируемыеОбъекты[БлокируемыйОбъект]; // Массив
|
||
СведенияОБлокируемомОбъекте.Добавить(Обработчик.ИмяОбработчика);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
ИначеЕсли ЗначениеЗаполнено(БлокируемыеОбъекты) И Не ЗначениеЗаполнено(ПроцедураПроверки) Тогда
|
||
ТекстИсключения = НСтр("ru = 'У отложенного обработчика обновления ""%1""
|
||
|заполнен список блокируемых объектов, но не задано свойство ""%2"".'");
|
||
|
||
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстИсключения, Обработчик.ИмяОбработчика, "ПроцедураПроверки");
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция НовыеСведенияОБлокируемыхОбъектах(СтарыеСведения = Неопределено)
|
||
|
||
СведенияОБлокируемыхОбъектах = Новый Структура;
|
||
СведенияОБлокируемыхОбъектах.Вставить("БлокируемыеОбъекты", Новый Соответствие);
|
||
СведенияОБлокируемыхОбъектах.Вставить("Обработчики", Новый Соответствие);
|
||
СведенияОБлокируемыхОбъектах.Вставить("РазблокированныеОбъекты", Новый Соответствие);
|
||
|
||
Если ТипЗнч(СтарыеСведения) = Тип("Структура") Тогда
|
||
ЗаполнитьЗначенияСвойств(СведенияОБлокируемыхОбъектах, СтарыеСведения);
|
||
КонецЕсли;
|
||
|
||
Возврат СведенияОБлокируемыхОбъектах;
|
||
|
||
КонецФункции
|
||
|
||
Процедура ЗаписатьСведенияОБлокируемыхОбъектах(Сведения) Экспорт
|
||
|
||
Если Сведения = Неопределено Тогда
|
||
НовоеЗначение = НовыеСведенияОБлокируемыхОбъектах();
|
||
Иначе
|
||
НовоеЗначение = Сведения;
|
||
КонецЕсли;
|
||
|
||
МенеджерКонстанты = Константы.СведенияОБлокируемыхОбъектах.СоздатьМенеджерЗначения();
|
||
МенеджерКонстанты.Значение = Новый ХранилищеЗначения(НовоеЗначение);
|
||
ОбновлениеИнформационнойБазы.ЗаписатьДанные(МенеджерКонстанты);
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ЗаполнитьДанныеДляПараллельногоОтложенногоОбновления(Параметры) Экспорт
|
||
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
ОтметитьРегистрациюОтложенныхОбработчиковОбновления();
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если Параметры.ПриЗапускеКлиентскогоПриложения
|
||
И Параметры.РежимВыполненияОтложенногоОбновления = "Отложенно" Тогда
|
||
КлиентСервер = Не ОбщегоНазначения.ИнформационнаяБазаФайловая();
|
||
Коробка = Не ОбщегоНазначения.РазделениеВключено();
|
||
|
||
Если КлиентСервер И Коробка Тогда
|
||
// Регистрация данных выполняется позже.
|
||
Возврат;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
ПерезапускОбновления = Параметры.Свойство("ПерезапускОбновления");
|
||
РегистрируемыеОбработчики = Новый Массив;
|
||
Если Параметры.Свойство("РегистрируемыеОбработчики") Тогда
|
||
РегистрируемыеОбработчики = Параметры.РегистрируемыеОбработчики;
|
||
КонецЕсли;
|
||
|
||
УдалитьВсеПотокиОбновления();
|
||
|
||
Если Не (СтандартныеПодсистемыПовтИсп.ИспользуетсяРИБ("СФильтром") И ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()) И Не ПерезапускОбновления Тогда
|
||
Запрос = Новый Запрос;
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбновлениеИнформационнойБазы.Ссылка КАК Узел
|
||
|ИЗ
|
||
| ПланОбмена.ОбновлениеИнформационнойБазы КАК ОбновлениеИнформационнойБазы
|
||
|ГДЕ
|
||
| НЕ ОбновлениеИнформационнойБазы.ЭтотУзел";
|
||
|
||
Выгрузка = Запрос.Выполнить().Выгрузить();
|
||
УзлыОбмена = Выгрузка.ВыгрузитьКолонку("Узел");
|
||
|
||
Для Каждого ЭлементСостава Из Метаданные.ПланыОбмена.ОбновлениеИнформационнойБазы.Состав Цикл
|
||
ПланыОбмена.УдалитьРегистрациюИзменений(УзлыОбмена, ЭлементСостава.Метаданные);
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
|
||
Если Не ОбщегоНазначения.ЭтоПодчиненныйУзелРИБ()
|
||
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.СброситьЗначениеКонстантыСИзменениямиДляПодчиненногоУзлаРИБСФильтрами();
|
||
КонецЕсли;
|
||
|
||
ПараметрыИнициализированы = Ложь;
|
||
|
||
Обработчики = ОбработчикиДляОтложеннойРегистрацииДанных(Ложь, ПерезапускОбновления, РегистрируемыеОбработчики);
|
||
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
|
||
Если Не ПараметрыИнициализированы Тогда
|
||
|
||
ПараметрыОбработчикаСтруктура = ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке();
|
||
ПараметрыИнициализированы = Истина;
|
||
|
||
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.ИнициализироватьФайлСДаннымиОбновления(ПараметрыОбработчикаСтруктура);
|
||
КонецЕсли;
|
||
|
||
КонецЕсли;
|
||
|
||
ПараметрыОбработчикаСтруктура.Очередь = Обработчик.ОчередьОтложеннойОбработки;
|
||
ПараметрыОбработчикаСтруктура.ИмяОбработчика = Обработчик.ИмяОбработчика;
|
||
ПараметрыОбработчикаСтруктура.Вставить("ДанныеОбработчика", Новый Соответствие);
|
||
ПараметрыОбработчикаСтруктура.Вставить("ПерезапускОбновления", ПерезапускОбновления);
|
||
|
||
Если Обработчик.Многопоточный Тогда
|
||
ПараметрыОбработчикаСтруктура.ПараметрыВыборки =
|
||
ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки();
|
||
Иначе
|
||
ПараметрыОбработчикаСтруктура.ПараметрыВыборки = Неопределено;
|
||
КонецЕсли;
|
||
|
||
ПараметрыОбработчика = Новый Массив;
|
||
ПараметрыОбработчика.Добавить(ПараметрыОбработчикаСтруктура);
|
||
Попытка
|
||
Сообщение = НСтр("ru = 'Выполняется процедура заполнения данных
|
||
|""%1""
|
||
|отложенного обработчика обновления
|
||
|""%2"".'");
|
||
Сообщение = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Сообщение,
|
||
Обработчик.ПроцедураЗаполненияДанныхОбновления,
|
||
Обработчик.ИмяОбработчика);
|
||
ЗаписатьИнформацию(Сообщение);
|
||
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(Обработчик.ПроцедураЗаполненияДанныхОбновления, ПараметрыОбработчика);
|
||
|
||
Если Обработчик.Многопоточный Тогда
|
||
ИсправитьПолныеИменаВПараметрахВыборки(ПараметрыОбработчикаСтруктура.ПараметрыВыборки);
|
||
КонецЕсли;
|
||
|
||
// Запись прогресса обновления.
|
||
Если Не ПерезапускОбновления И Параметры.ВФоне Тогда
|
||
ХодВыполненияОбработчиков = Параметры.ХодВыполненияОбработчиков;
|
||
ХодВыполненияОбработчиков.ВыполненоОбработчиков = ХодВыполненияОбработчиков.ВыполненоОбработчиков + 1;
|
||
Прогресс = 10 + ХодВыполненияОбработчиков.ВыполненоОбработчиков / ХодВыполненияОбработчиков.ВсегоОбработчиков * 90;
|
||
ДлительныеОперации.СообщитьПрогресс(Прогресс);
|
||
КонецЕсли;
|
||
Исключение
|
||
Если Не ПерезапускОбновления Тогда
|
||
ОтметитьРегистрациюОтложенныхОбработчиковОбновления(Обработчик.ИмяБиблиотеки, Ложь);
|
||
КонецЕсли;
|
||
|
||
ЗаписатьОшибку(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
|
||
НСтр("ru = 'При вызове процедуры заполнения данных
|
||
|""%1""
|
||
|отложенного обработчика обновления
|
||
|""%2""
|
||
|произошла ошибка:
|
||
|""%3"".'"),
|
||
Обработчик.ПроцедураЗаполненияДанныхОбновления,
|
||
Обработчик.ИмяОбработчика,
|
||
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
|
||
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
ОписаниеОбрабатываемыхДанных = НовоеОписаниеОбрабатываемыхДанных(Обработчик.Многопоточный);
|
||
ОписаниеОбрабатываемыхДанных.ДанныеОбработчика = ПараметрыОбработчикаСтруктура.ДанныеОбработчика;
|
||
ОписаниеОбрабатываемыхДанных.ИмяОбработчика = Обработчик.ИмяОбработчика;
|
||
|
||
Если Обработчик.Многопоточный Тогда
|
||
ОписаниеОбрабатываемыхДанных.ПараметрыВыборки = ПараметрыОбработчикаСтруктура.ПараметрыВыборки;
|
||
КонецЕсли;
|
||
|
||
ОписаниеОбрабатываемыхДанных = Новый ХранилищеЗначения(ОписаниеОбрабатываемыхДанных, Новый СжатиеДанных(9));
|
||
УстановитьСвойствоОбработчика(Обработчик.ИмяОбработчика, "ОбрабатываемыеДанные", ОписаниеОбрабатываемыхДанных);
|
||
|
||
КонецЦикла;
|
||
|
||
Если Не ПерезапускОбновления Тогда
|
||
ОтметитьРегистрациюОтложенныхОбработчиковОбновления();
|
||
КонецЕсли;
|
||
|
||
Если ПараметрыИнициализированы И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.ЗавершитьЗаписьФайлаСДаннымиОбновления(ПараметрыОбработчикаСтруктура);
|
||
КонецЕсли;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Заполнить данные для параллельного отложенного обновления в фоне, используя несколько потоков.
|
||
//
|
||
// Параметры:
|
||
// ИдентификаторФормы - УникальныйИдентификатор - идентификатор формы, отображающей процесс обновления.
|
||
// АдресРезультата - Строка - адрес временного хранилища с результатом выполнения процедуры.
|
||
//
|
||
Процедура ЗапускРегистрацииДанныхОтложенногоОбновления(ИдентификаторФормы, АдресРезультата) Экспорт
|
||
|
||
Группы = НовоеОписаниеГруппПотоковРегистрацииДанныхОтложенногоОбновления();
|
||
|
||
Обработчики = ОбработчикиДляОтложеннойРегистрацииДанных();
|
||
УдалитьВсеПотокиОбновления();
|
||
|
||
Попытка
|
||
ДоступнаПакетнаяРегистрация = ОбновлениеИнформационнойБазы.ДоступнаПакетнаяРегистрация();
|
||
|
||
Если ДоступнаПакетнаяРегистрация Тогда
|
||
ТекущаяОчередь = ?(Обработчики.Количество() > 0, Обработчики[0].ОчередьОтложеннойОбработки, 0);
|
||
КонецЕсли;
|
||
Для Каждого Обработчик Из Обработчики Цикл
|
||
Если ДоступнаПакетнаяРегистрация И Обработчик.ОчередьОтложеннойОбработки > ТекущаяОчередь Тогда
|
||
ОжидатьЗавершениеВсехПотоков(Группы);
|
||
ТекущаяОчередь = Обработчик.ОчередьОтложеннойОбработки;
|
||
КонецЕсли;
|
||
|
||
ОписаниеОбрабатываемыхДанных = Обработчик.ОбрабатываемыеДанные.Получить();
|
||
|
||
Поток = ДобавитьПотокРегистрацииДанныхОтложенногоОбновления(ОписаниеОбрабатываемыхДанных);
|
||
ВыполнитьПоток(Группы, Поток, ИдентификаторФормы);
|
||
ОжидатьСвободныйПоток(Группы);
|
||
КонецЦикла;
|
||
|
||
ОжидатьЗавершениеВсехПотоков(Группы);
|
||
УдалитьВсеПотокиОбновления();
|
||
Исключение
|
||
ОтменитьВыполнениеВсехПотоков(Группы);
|
||
УдалитьВсеПотокиОбновления();
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Заполнение данных отложенного обработчика в фоновом задании.
|
||
//
|
||
// Параметры:
|
||
// ОписаниеОбрабатываемыхДанных - см. НовоеОписаниеОбрабатываемыхДанных
|
||
// АдресРезультата - Строка - адрес временного хранилища для сохранения результата выполнения процедуры.
|
||
//
|
||
Процедура ЗаполнитьДанныеОтложенногоОбработчика(ОписаниеОбрабатываемыхДанных, АдресРезультата) Экспорт
|
||
|
||
ПараметрыОтметкиКОбработке = ОбновлениеИнформационнойБазы.ОсновныеПараметрыОтметкиКОбработке();
|
||
ЕстьПодсистемаОбменаДанными = ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными");
|
||
|
||
Если ЕстьПодсистемаОбменаДанными Тогда
|
||
МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
|
||
МодульОбменДаннымиСервер.ИнициализироватьФайлСДаннымиОбновления(ПараметрыОтметкиКОбработке);
|
||
КонецЕсли;
|
||
|
||
ПараметрыОтметкиКОбработке.Очередь = ОписаниеОбрабатываемыхДанных.Очередь;
|
||
ПараметрыОтметкиКОбработке.ИмяОбработчика = ОписаниеОбрабатываемыхДанных.ИмяОбработчика;
|
||
ПараметрыОтметкиКОбработке.Вставить("ДанныеОбработчика", Новый Соответствие);
|
||
МногопоточныйРежим = ЭтоОписаниеДанныхМногопоточногоОбработчика(ОписаниеОбрабатываемыхДанных);
|
||
|
||
Если МногопоточныйРежим Тогда
|
||
ПараметрыОтметкиКОбработке.ПараметрыВыборки =
|
||
ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки();
|
||
Иначе
|
||
ПараметрыОтметкиКОбработке.ПараметрыВыборки = Неопределено;
|
||
КонецЕсли;
|
||
|
||
ПараметрыОбработчика = Новый Массив;
|
||
ПараметрыОбработчика.Добавить(ПараметрыОтметкиКОбработке);
|
||
|
||
ШаблонСообщения = НСтр(
|
||
"ru = 'Выполняется процедура заполнения данных
|
||
|""%1""
|
||
|отложенного обработчика обновления
|
||
|""%2"".'");
|
||
ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонСообщения,
|
||
ОписаниеОбрабатываемыхДанных.ПроцедураЗаполнения,
|
||
ОписаниеОбрабатываемыхДанных.ИмяОбработчика);
|
||
ЗаписатьИнформацию(ТекстСообщения);
|
||
|
||
Попытка
|
||
ОбщегоНазначения.ВыполнитьМетодКонфигурации(ОписаниеОбрабатываемыхДанных.ПроцедураЗаполнения, ПараметрыОбработчика);
|
||
Исключение
|
||
ИнформацияОбОшибке = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
|
||
ШаблонОшибки = НСтр(
|
||
"ru = 'При вызове процедуры заполнения данных
|
||
|""%1""
|
||
|отложенного обработчика обновления
|
||
|""%2""
|
||
|произошла ошибка:
|
||
|""%3"".'");
|
||
ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОшибки,
|
||
ОписаниеОбрабатываемыхДанных.ПроцедураЗаполнения,
|
||
ОписаниеОбрабатываемыхДанных.ИмяОбработчика,
|
||
ИнформацияОбОшибке);
|
||
ЗаписатьОшибку(ТекстСообщения);
|
||
ВызватьИсключение;
|
||
КонецПопытки;
|
||
|
||
Результат = Новый Структура;
|
||
Результат.Вставить("ДанныеОбработчика", ПараметрыОтметкиКОбработке.ДанныеОбработчика);
|
||
|
||
Если МногопоточныйРежим Тогда
|
||
Результат.Вставить("ПараметрыВыборки", ПараметрыОтметкиКОбработке.ПараметрыВыборки);
|
||
КонецЕсли;
|
||
|
||
Если ЕстьПодсистемаОбменаДанными Тогда
|
||
ДанныеОбновления = МодульОбменДаннымиСервер.ЗавершитьЗаписьФайлаИПолучитьДанныеОбновления(ПараметрыОтметкиКОбработке);
|
||
Результат.Вставить("ДанныеОбновления", ДанныеОбновления);
|
||
Результат.Вставить("ИмяФайлаСИзменениями", ПараметрыОтметкиКОбработке.ИмяФайлаСИзменениями);
|
||
КонецЕсли;
|
||
|
||
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура УстановитьПараметрыОбработчикаОбновления(ОбработчикОбновления, Отложенно = Ложь, Параллельно = Ложь)
|
||
|
||
Если ОбработчикОбновления = Неопределено Тогда
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(НовыеПараметрыОбработчикаОбновления());
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Если Отложенно Тогда
|
||
РежимВыполнения = "Отложенно";
|
||
ИмяОбработчика = ОбработчикОбновления.ИмяОбработчика;
|
||
Иначе
|
||
РежимВыполнения = "Монопольно";
|
||
ИмяОбработчика = ОбработчикОбновления.Процедура;
|
||
КонецЕсли;
|
||
|
||
Если Параллельно Тогда
|
||
РежимВыполненияОтложенныхОбработчиков = "Параллельно";
|
||
Иначе
|
||
РежимВыполненияОтложенныхОбработчиков = "Последовательно";
|
||
КонецЕсли;
|
||
|
||
ПолучениеСвойств = Новый Структура;
|
||
ПолучениеСвойств.Вставить("ИзменяемыеОбъекты", "");
|
||
ЗаполнитьЗначенияСвойств(ПолучениеСвойств, ОбработчикОбновления);
|
||
|
||
ПараметрыОбработчикаОбновления = НовыеПараметрыОбработчикаОбновления();
|
||
ПараметрыОбработчикаОбновления.ЗапускатьТолькоВГлавномУзле = ОбработчикОбновления.ЗапускатьТолькоВГлавномУзле;
|
||
ПараметрыОбработчикаОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами = ОбработчикОбновления.ЗапускатьИВПодчиненномУзлеРИБСФильтрами;
|
||
ПараметрыОбработчикаОбновления.ОчередьОтложеннойОбработки = ОбработчикОбновления.ОчередьОтложеннойОбработки;
|
||
ПараметрыОбработчикаОбновления.РежимВыполнения = РежимВыполнения;
|
||
ПараметрыОбработчикаОбновления.РежимВыполненияОтложенныхОбработчиков = РежимВыполненияОтложенныхОбработчиков;
|
||
ПараметрыОбработчикаОбновления.КлючЗаписиПрогрессаОбновления = Новый УникальныйИдентификатор;
|
||
ПараметрыОбработчикаОбновления.ЕстьОбработанныеОбъекты = Ложь;
|
||
ПараметрыОбработчикаОбновления.ИмяОбработчика = ИмяОбработчика;
|
||
ПараметрыОбработчикаОбновления.ИзменяемыеОбъекты = УникальныеЗначенияЧерезЗапятую(ПолучениеСвойств.ИзменяемыеОбъекты);
|
||
|
||
ПараметрыСеанса.ПараметрыОбработчикаОбновления = Новый ФиксированнаяСтруктура(ПараметрыОбработчикаОбновления);
|
||
|
||
КонецПроцедуры
|
||
|
||
Функция НовыеПараметрыОбработчикаОбновления() Экспорт
|
||
ПараметрыОбработчикаОбновления = Новый Структура;
|
||
ПараметрыОбработчикаОбновления.Вставить("ЗапускатьТолькоВГлавномУзле", Ложь);
|
||
ПараметрыОбработчикаОбновления.Вставить("ЗапускатьИВПодчиненномУзлеРИБСФильтрами", Ложь);
|
||
ПараметрыОбработчикаОбновления.Вставить("ОчередьОтложеннойОбработки", 0);
|
||
ПараметрыОбработчикаОбновления.Вставить("РежимВыполнения", "");
|
||
ПараметрыОбработчикаОбновления.Вставить("РежимВыполненияОтложенныхОбработчиков", "");
|
||
ПараметрыОбработчикаОбновления.Вставить("ЕстьОбработанныеОбъекты", Ложь);
|
||
ПараметрыОбработчикаОбновления.Вставить("КлючЗаписиПрогрессаОбновления", Неопределено);
|
||
ПараметрыОбработчикаОбновления.Вставить("ИмяОбработчика", "");
|
||
ПараметрыОбработчикаОбновления.Вставить("ИзменяемыеОбъекты", "");
|
||
|
||
Возврат ПараметрыОбработчикаОбновления;
|
||
КонецФункции
|
||
|
||
// Обработать исключение, возникшее при подготовке или завершении выполнения обработчика в основном потоке.
|
||
//
|
||
// Параметры:
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// ОбработчикОбновления - СтрокаДереваЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
//
|
||
Процедура ОбработатьИсключениеОбработчика(КонтекстОбработчика, ОбработчикОбновления, ИнформацияОбОшибке)
|
||
|
||
Если КонтекстОбработчика.ЗаписыватьВЖурнал Тогда
|
||
ЗаписатьДетальнуюИнформациюОХодеОбновления(КонтекстОбработчика.ДетальноеОписаниеОбработчика);
|
||
КонецЕсли;
|
||
|
||
// АПК:325-выкл откат незакрытых транзакций после выполнения обработчика.
|
||
Если Не КонтекстОбработчика.Свойство("ПропуститьОтменуТранзакций") Тогда
|
||
Пока ТранзакцияАктивна() Цикл
|
||
ОтменитьТранзакцию();
|
||
КонецЦикла;
|
||
КонецЕсли;
|
||
// АПК:325-вкл
|
||
|
||
ДобавляемоеЧислоПопыток = ДобавляемоеЧислоПопыток(ОбработчикОбновления, КонтекстОбработчика, Истина);
|
||
ЧислоПопыток = ОбработчикОбновления.ЧислоПопыток + ДобавляемоеЧислоПопыток;
|
||
ПодробноеПредставлениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
|
||
|
||
МаксимумПопытокОбновления = МаксимумПопытокОбновления(ОбработчикОбновления);
|
||
|
||
Если ЧислоПопыток < МаксимумПопытокОбновления Тогда
|
||
ЗаписатьПредупреждение(ПодробноеПредставлениеОшибки);
|
||
Иначе
|
||
ОбновлениеИнформационнойБазы.ЗаписатьСобытиеВЖурналРегистрации(ПодробноеПредставлениеОшибки, , КонтекстОбработчика.Параметры);
|
||
КонецЕсли;
|
||
|
||
Свойства = Новый Структура;
|
||
Свойства.Вставить("ЧислоПопыток", ЧислоПопыток);
|
||
Свойства.Вставить("Статус", Перечисления.СтатусыОбработчиковОбновления.Ошибка);
|
||
Свойства.Вставить("ИнформацияОбОшибке", ПодробноеПредставлениеОшибки);
|
||
УстановитьСвойстваОбработчика(ОбработчикОбновления.ИмяОбработчика, Свойства);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Обработать СуществующиеПоставляемыеЭлементы, полученный в результате разбиения результата поиска данных для
|
||
// обновления, в отдельном потоке.
|
||
//
|
||
// Параметры:
|
||
// СуществующиеПоставляемыеЭлементы - Массив из см. НовыйНаборПорцийДляОбновления
|
||
// ОписаниеПотоков - см. НовоеОписаниеПотоков
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
//
|
||
Процедура ОбработатьФрагментДанныхВПотоке(Фрагмент, Группы, КонтекстОбработчика)
|
||
|
||
КонтекстОбработчикаДляПотока = ОбщегоНазначения.СкопироватьРекурсивно(КонтекстОбработчика); // см. НовыйКонтекстОбработчика
|
||
КонтекстОбработчикаДляПотока.Параметры.ОбновляемыеДанные = Фрагмент;
|
||
Поток = НовыйПоток();
|
||
ДобавитьПотокОбработчикаОбновления(Поток, КонтекстОбработчикаДляПотока);
|
||
ВыполнитьПоток(Группы, Поток);
|
||
КонтекстОбработчикаДляПотока.Параметры.ОбновляемыеДанные.НаборДанных = Неопределено;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Устанавливает статус ошибки у всех зациклившихся обработчиков.
|
||
//
|
||
Процедура ОтметитьЗациклившиесяОбработчики()
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполняется);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.Статус КАК Статус,
|
||
| ОбработчикиОбновления.ЧислоПопыток КАК ЧислоПопыток,
|
||
| ОбработчикиОбновления.Многопоточный,
|
||
| ОбработчикиОбновления.ОбрабатываемыеДанные
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.Статус = &Статус";
|
||
Выполняющиеся = Запрос.Выполнить().Выгрузить();
|
||
|
||
Для каждого ОбработчикОбновления Из Выполняющиеся Цикл
|
||
МаксимумПопыток = МаксимумПопытокОбновления(ОбработчикОбновления) - 1;
|
||
|
||
Если ОбработчикОбновления.ЧислоПопыток >= МаксимумПопыток Тогда
|
||
ИнформацияОбОшибке = НСтр("ru = 'Произошло зацикливание процедуры обработки данных. Выполнение прервано.'");
|
||
УстановитьСтатусОбработчика(ОбработчикОбновления.ИмяОбработчика, "Ошибка", ИнформацияОбОшибке);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
КонецПроцедуры
|
||
|
||
// Проверяет, все ли выполняемые обработчики зациклились.
|
||
// Условия зацикливания:
|
||
// - все выполняющиеся обработчики имеют число попыток >= 2;
|
||
// - или
|
||
// - есть минимум один выполняющийся обработчик с числом попыток >= 2
|
||
// - и
|
||
// - есть минимум один обработчик, завершенный с ошибкой.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Булево - Истина, если обработчики зациклились.
|
||
//
|
||
Функция ВсеОбработчикиЗациклились()
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполняется);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| ОбработчикиОбновления.ИмяОбработчика КАК ИмяОбработчика,
|
||
| ОбработчикиОбновления.Многопоточный КАК Многопоточный,
|
||
| ОбработчикиОбновления.ОбрабатываемыеДанные КАК ОбрабатываемыеДанные,
|
||
| ОбработчикиОбновления.Статус КАК Статус,
|
||
| ОбработчикиОбновления.ЧислоПопыток КАК ЧислоПопыток
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.Статус = &Статус";
|
||
Выполняющиеся = Запрос.Выполнить().Выгрузить();
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Ошибка);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ ПЕРВЫЕ 1
|
||
| ИСТИНА
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.Статус = &Статус";
|
||
СОшибками = Запрос.Выполнить().Выгрузить();
|
||
|
||
Если Выполняющиеся.Количество() > 0 Тогда
|
||
ЕстьПревысившие = Ложь;
|
||
ЕстьНормальные = Ложь;
|
||
|
||
Для каждого ОбработчикОбновления Из Выполняющиеся Цикл
|
||
МаксимумПопыток = МаксимумПопытокОбновления(ОбработчикОбновления) - 1;
|
||
|
||
Если ОбработчикОбновления.ЧислоПопыток < МаксимумПопыток Тогда
|
||
ЕстьНормальные = Истина;
|
||
Иначе
|
||
ЕстьПревысившие = Истина;
|
||
КонецЕсли;
|
||
|
||
Если ЕстьНормальные И ЕстьПревысившие Тогда
|
||
Прервать;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Если ЕстьПревысившие Тогда
|
||
Если ЕстьНормальные Тогда
|
||
Возврат СОшибками.Количество() > 0;
|
||
Иначе
|
||
Возврат Истина;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат Ложь;
|
||
|
||
КонецФункции
|
||
|
||
// Получить количество запусков процедуры обновления.
|
||
//
|
||
// Параметры:
|
||
// ОбработчикОбновления - СтрокаДереваЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - количество запусков.
|
||
//
|
||
Функция КоличествоЗапусковПроцедурыОбновления(СтатистикаВыполнения)
|
||
|
||
КоличествоЗапусковПроцедурыОбновления = СтатистикаВыполнения["КоличествоЗапусков"];
|
||
|
||
Если КоличествоЗапусковПроцедурыОбновления = Неопределено Тогда
|
||
КоличествоЗапусковПроцедурыОбновления = 0;
|
||
КонецЕсли;
|
||
|
||
Возврат КоличествоЗапусковПроцедурыОбновления;
|
||
|
||
КонецФункции
|
||
|
||
// Возвращает максимальное количество попыток обновления для указанного обработчика обновления.
|
||
//
|
||
// Параметры:
|
||
// ОбработчикОбновления - СтрокаТаблицыЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - максимальное количество попыток обновления.
|
||
//
|
||
Функция МаксимумПопытокОбновления(ОбработчикОбновления)
|
||
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
ОбрабатываемыеДанные = ОбработчикОбновления.ОбрабатываемыеДанные.Получить();
|
||
ПараметрыВыборки = ОбрабатываемыеДанные.ПараметрыВыборки;
|
||
ПолныеИменаОбъектов = ПараметрыВыборки.ПолныеИменаОбъектов;
|
||
ПолныеИменаРегистров = ПараметрыВыборки.ПолныеИменаРегистров;
|
||
СоставОбъектов = СтрРазделить(ПолныеИменаОбъектов, ",");
|
||
СоставРегистров = СтрРазделить(ПолныеИменаРегистров, ",");
|
||
КоличествоПотоков = КоличествоПотоковОбновленияИнформационнойБазы();
|
||
Множитель = СоставОбъектов.Количество() * СоставРегистров.Количество() + КоличествоПотоков;
|
||
Иначе
|
||
Множитель = 1;
|
||
КонецЕсли;
|
||
|
||
Возврат 3 * Множитель;
|
||
|
||
КонецФункции
|
||
|
||
// Количество добавляемых попыток для счетчика ЧислоПопыток.
|
||
//
|
||
// Параметры:
|
||
// ОбработчикОбновления - СтрокаДереваЗначений - обработчик обновления в виде строки дерева обработчиков.
|
||
// КонтекстОбработчика - см. НовыйКонтекстОбработчика
|
||
// Ошибка - Булево - Истина, если в обработчике обновления возникла ошибка.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Число - 0, если это многопоточный обработчик, которому не были переданы данные для обновления, иначе 1.
|
||
//
|
||
Функция ДобавляемоеЧислоПопыток(ОбработчикОбновления, КонтекстОбработчика, Ошибка = Ложь)
|
||
|
||
Если ОбработчикОбновления.Многопоточный Тогда
|
||
Если КонтекстОбработчика.Параметры.Свойство("ОбновляемыеДанные") Тогда
|
||
ОбновляемыеДанные = КонтекстОбработчика.Параметры.ОбновляемыеДанные;
|
||
Иначе
|
||
ОбновляемыеДанные = Неопределено;
|
||
КонецЕсли;
|
||
|
||
// Проверяется по полям ОбновляемыеДанные.ПерваяЗапись и ОбновляемыеДанные.ПоследняяЗапись, а не по полю
|
||
// ОбновляемыеДанные.НаборДанных, т.к. оно очищается в ОбработатьФрагментДанныхВПотоке() для экономии памяти.
|
||
// ОбновляемыеДанные может быть Неопределено, если обработчик выбросил исключение.
|
||
Если ОбновляемыеДанные <> Неопределено Тогда
|
||
ЕстьДанные = ОбновляемыеДанные.ПерваяЗапись <> Неопределено Или ОбновляемыеДанные.ПоследняяЗапись <> Неопределено;
|
||
Если Не ЕстьДанные И Не Ошибка Тогда
|
||
Возврат 0;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
КонецЕсли;
|
||
|
||
Возврат 1;
|
||
|
||
КонецФункции
|
||
|
||
Функция МинимальнаяОчередьОтложеннойОбработки()
|
||
|
||
Запрос = Новый Запрос;
|
||
Запрос.УстановитьПараметр("РежимВыполнения", Перечисления.РежимыВыполненияОбработчиков.Отложенно);
|
||
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбработчиковОбновления.Выполнен);
|
||
Запрос.УстановитьПараметр("РежимВыполненияОтложенногоОбработчика", Перечисления.РежимыВыполненияОтложенныхОбработчиков.Параллельно);
|
||
Запрос.Текст =
|
||
"ВЫБРАТЬ
|
||
| МИНИМУМ(ОбработчикиОбновления.ОчередьОтложеннойОбработки) КАК Очередь
|
||
|ИЗ
|
||
| РегистрСведений.ОбработчикиОбновления КАК ОбработчикиОбновления
|
||
|ГДЕ
|
||
| ОбработчикиОбновления.РежимВыполнения = &РежимВыполнения
|
||
| И ОбработчикиОбновления.РежимВыполненияОтложенногоОбработчика = &РежимВыполненияОтложенногоОбработчика
|
||
| И ОбработчикиОбновления.Статус <> &Статус";
|
||
Результат = Запрос.Выполнить().Выгрузить();
|
||
|
||
Возврат Результат[0].Очередь;
|
||
|
||
КонецФункции
|
||
|
||
Функция ОстатокМассива(Массив, ЗначениеНачала)
|
||
|
||
ОстатокМассива = Новый Массив;
|
||
ТочноеЗначениеНачала = СокрЛП(ЗначениеНачала);
|
||
ЗначениеНайдено = Ложь;
|
||
|
||
Для Каждого Элемент Из СтрРазделитьСокрЛП(Массив, ",") Цикл
|
||
Если ТочноеЗначениеНачала = Элемент Тогда
|
||
ЗначениеНайдено = Истина;
|
||
КонецЕсли;
|
||
|
||
Если ЗначениеНайдено Тогда
|
||
ОстатокМассива.Добавить(Элемент);
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Возврат ОстатокМассива;
|
||
|
||
КонецФункции
|
||
|
||
// Исправить перечисленные через запятую полные имена объектов и регистров
|
||
// с помощью УникальныеЗначенияЧерезЗапятую, чтобы не сбивалась курсорная выборка данных.
|
||
//
|
||
// Параметры:
|
||
// ПараметрыВыборки - см. ОбновлениеИнформационнойБазы.ДополнительныеПараметрыВыборкиДанныхДляМногопоточнойОбработки
|
||
//
|
||
Процедура ИсправитьПолныеИменаВПараметрахВыборки(ПараметрыВыборки)
|
||
|
||
ПараметрыВыборки.ПолныеИменаОбъектов = УникальныеЗначенияЧерезЗапятую(ПараметрыВыборки.ПолныеИменаОбъектов);
|
||
ПараметрыВыборки.ПолныеИменаРегистров = УникальныеЗначенияЧерезЗапятую(ПараметрыВыборки.ПолныеИменаРегистров);
|
||
|
||
КонецПроцедуры
|
||
|
||
// Оставить только уникальные значения, перечисленные через запятую и упорядочить их.
|
||
//
|
||
// Параметры:
|
||
// Строка - Строка - значения, перечисленные через запятую.
|
||
//
|
||
// Возвращаемое значение:
|
||
// Строка - только уникальные упорядоченные значения через запятую.
|
||
//
|
||
Функция УникальныеЗначенияЧерезЗапятую(Строка)
|
||
|
||
Если Строка = Неопределено Тогда
|
||
Возврат Неопределено;
|
||
КонецЕсли;
|
||
|
||
Значения = СтрРазделить(Строка, ",");
|
||
Таблица = Новый ТаблицаЗначений;
|
||
Таблица.Колонки.Добавить("Значение");
|
||
|
||
Для Каждого Значение Из Значения Цикл
|
||
ТочноеЗначение = СокрЛП(Значение);
|
||
|
||
Если Не ПустаяСтрока(ТочноеЗначение) Тогда
|
||
СтрокаТаблицы = Таблица.Добавить();
|
||
СтрокаТаблицы.Значение = ТочноеЗначение;
|
||
КонецЕсли;
|
||
КонецЦикла;
|
||
|
||
Таблица.Свернуть("Значение");
|
||
Таблица.Сортировать("Значение");
|
||
Значения = Таблица.ВыгрузитьКолонку("Значение");
|
||
|
||
Возврат СтрСоединить(Значения, ",");
|
||
|
||
КонецФункции
|
||
|
||
Функция РасшифровкаЯчейки(Статус, ЕстьОшибки, ПроблемаВДанных) Экспорт
|
||
Массив = Новый Массив;
|
||
Массив.Добавить(Статус);
|
||
Массив.Добавить(ЕстьОшибки);
|
||
Массив.Добавить(ПроблемаВДанных);
|
||
Возврат Массив;
|
||
КонецФункции
|
||
|
||
Процедура СброситьПрогрессВыполненияОбработчиков()
|
||
|
||
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
Набор = РегистрыСведений.ПрогрессОбновления.СоздатьНаборЗаписей();
|
||
Набор.Записать();
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура ДобавитьИнформациюОбОшибкеВОбработчике(ИмяОбработчика) Экспорт
|
||
|
||
Если Не ЗначениеЗаполнено(ИмяОбработчика) Тогда
|
||
ТекстОшибки = НСтр("ru = 'Не удалось сохранить информацию об ошибке в обработчике
|
||
|по причине:
|
||
|Возможно вызов выполняется не из обработчика обновления.'");
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
Возврат;
|
||
КонецЕсли;
|
||
|
||
БлокировкаДанных = Новый БлокировкаДанных;
|
||
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("РегистрСведений.ОбработчикиОбновления");
|
||
ЭлементБлокировкиДанных.УстановитьЗначение("ИмяОбработчика", ИмяОбработчика);
|
||
НачатьТранзакцию();
|
||
Попытка
|
||
БлокировкаДанных.Заблокировать();
|
||
|
||
МенеджерЗаписи = РегистрыСведений.ОбработчикиОбновления.СоздатьМенеджерЗаписи();
|
||
МенеджерЗаписи.ИмяОбработчика = ИмяОбработчика;
|
||
МенеджерЗаписи.Прочитать();
|
||
|
||
СтатистикаВыполнения = МенеджерЗаписи.СтатистикаВыполнения;
|
||
СтатистикаВыполнения = СтатистикаВыполнения.Получить();
|
||
СтатистикаВыполнения.Вставить("ЕстьОшибки", Истина);
|
||
МенеджерЗаписи.СтатистикаВыполнения = Новый ХранилищеЗначения(СтатистикаВыполнения);
|
||
МенеджерЗаписи.Записать();
|
||
|
||
ЗафиксироватьТранзакцию();
|
||
Исключение
|
||
ОтменитьТранзакцию();
|
||
ИнформацияОбОшибке = ИнформацияОбОшибке();
|
||
ТекстОшибки = НСтр("ru = 'Не удалось сохранить информацию об ошибке в обработчике %1
|
||
|по причине:
|
||
|%2'");
|
||
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстОшибки,
|
||
ИмяОбработчика, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
|
||
ЗаписатьОшибку(ТекстОшибки);
|
||
КонецПопытки
|
||
|
||
КонецПроцедуры
|
||
|
||
Процедура Пауза(Секунд) Экспорт
|
||
|
||
ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
|
||
ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
|
||
|
||
Если ФоновоеЗадание = Неопределено Тогда
|
||
Параметры = Новый Массив;
|
||
Параметры.Добавить(Секунд);
|
||
ФоновоеЗадание = ФоновыеЗадания.Выполнить("ОбновлениеИнформационнойБазыСлужебный.Пауза", Параметры);
|
||
КонецЕсли;
|
||
|
||
ФоновоеЗадание.ОжидатьЗавершенияВыполнения(Секунд);
|
||
|
||
КонецПроцедуры
|
||
|
||
#КонецОбласти |