Два своих диапазона в памяти: найти пересечение и проверить изменение20→18→20

Учебные задачи

Создаем настоящие native диапазоны явными числовыми аргументами, перечитываем обе границы после каждого setter и считаем свой включенный план. Не подключаемся к серверу и не проверяем доступность портов.

Где и как запускать

Платформа8.5.1.1343; серверный общий модуль собственной новой File CF; толстая управляемая форма отображает только восемь чисел. Runtime1C/CF/UI не выполнялись.

Подготовка

  1. Задача: еще до любой настройки сервера найти пересечение двух предполагаемых диапазонов. Здесь числа портов — только целые числа в маленьких массивах. Мы принимаем свое правило планировщика: включаем обе границы. Это НЕ утверждение о том, как платформа фактически назначает адреса рабочим процессам.

  2. Вручную создайте НОВУЮ пустую файловую CF только C:\1c-labs\OwnPortRangePlanner85_d5827fb0-6c4a-4879-b9e8-73517ef85d6b\IB. Имя конфигурации УчебныйПланДиапазонов85, РежимСовместимостиНеИспользовать, основное приложениеУправляемоеПриложение. Windows, платформа8.5.1.1343, толстый управляемый клиент. Код требует точную native строку File="путь"; и не принимает иной каталог/суффикс/формат регистрации. UUID в пути — маркер лаборатории, не UUID информационной базы.

  3. Оставьте конфигурацию без справочников, документов и всех четырех видов регистров, без расширений. Создайте собственную роль Порты85Администратор с полными правами только этой новой CF, включая администрирование для ПолучитьПользователей. Создайте единственного собственного пользователя Порты85Ученик и назначьте роль. Реальные Users.Count1 и UUID текущего пользователя сверяются до создания диапазонов. Эти действия здесь не выполнялись; не переносите пример в рабочую УТ/КА/УНФ/БП.

  4. Общие→ОбщиеМодули→ПланДиапазоновПамять85. СерверДа, оба клиентских контекстаНет, ГлобальныйНет, ВызовСервераНет, ПривилегированныйНет. Вставьте полный основной CODE. Только серверная процедура своей формы вызывает экспортную функцию этого модуля без внешних объектов и параметров.

  5. Общие→ОбщиеФормы→ПроверкаДиапазонов85, управляемая форма. Создайте реквизиты До85, Изменено85, Восстановлено85, ПересечениеДо85, ПересечениеИзменено85, ПересечениеВосстановлено85, НижняяA85, ВерхняяA85 — Число, длина10, точность0. Протокол85 — Строка неограниченной длины; Остановка85 и Завершено85 — Булево с исходным значениемЛожь. Выведите восемь числовых полей и многострочный Протокол85 только для просмотра; флаги пользователю не выводите.

  6. В этой форме добавьте единственную команду Выполнить85; свойствоДействие→обработчикВыполнить85(Команда). Создайте кнопку с Команда=Выполнить85 на командной панели. Вставьте целиком supporting module ПроверкаДиапазонов85, включая серверную процедуру. Не вызывайте обработчик вручную и не создавайте второй экземпляр формы в ходе одного протокола.

  7. Конфигурация→Открыть модуль управляемого приложения: вставьте supporting module УправляемоеПриложение. Штатное событие ПриНачалеРаботыСистемы без параметров откроет только свою общую форму. Вручную обновите новую учебную конфигурацию и запустите Предприятие собственным пользователем в толстом управляемом клиенте. Никаких RAS, ragent, сервера1С, подключения к кластеру или свободных портов для этого memory урока не требуется.

  8. Нажмите Выполнить85 один раз. После успеха либо исключения команда запрещает повтор. Если возник отказ, изучите точную ошибку в отладчике своего стенда; не возобновляйте выполнение после исключения и не восстанавливайте границы наугад. Для нового ручного протокола закройте собственный клиент и начните заново — никаких чужих процессов завершать не надо.

  9. В этой работе изготовлены и статически проверены тексты, native контракты и отрицательные тесты. Файловая ИБ, CF, пользователи, обновление конфигурации, реальный запуск1С и UI здесь не создавались и не выполнялись. Ожидаемые будущие числа ниже не являются полученным runtime результатом.

Процедура ПроверитьСвойСтенд85()
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnPortRangePlanner85_d5827fb0-6c4a-4879-b9e8-73517ef85d6b\IB"";" Тогда
        ВызватьИсключение "Только свой точно подготовленный File-стенд 8.5.1.1343";
    КонецЕсли;
    Если Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеМодули.Найти("ПланДиапазоновПамять85") = Неопределено
        Или Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("ПроверкаДиапазонов85") = Неопределено
        Или Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
        Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
        Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Тогда
        ВызватьИсключение "Нужны только свои общий модуль и общая форма; прикладных объектов быть не должно";
    КонецЕсли;
    Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
        Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
        Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
        ВызватьИсключение "Собственный учебный стенд должен быть без расширений";
    КонецЕсли;
    Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Если Текущий = Неопределено Или Пользователи.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный реальный собственный пользователь ИБ";
    КонецЕсли;
    Если Текущий.Имя <> "Порты85Ученик" Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
        ВызватьИсключение "Настоящий UUID текущего пользователя не совпал с собственным единственным пользователем";
    КонецЕсли;
КонецПроцедуры

Функция ПрочитатьСвойДиапазон85(Диапазон, ОжидаемаяНижняя, ОжидаемаяВерхняя)
    Если ТипЗнч(Диапазон) <> Тип("АдминистрированиеДиапазонПортов") Тогда
        ВызватьИсключение "Нет настоящего собственного native диапазона";
    КонецЕсли;
    Нижняя = Диапазон.НижняяГраница;
    Верхняя = Диапазон.ВерхняяГраница;
    Если ТипЗнч(Нижняя) <> Тип("Число") Или ТипЗнч(Верхняя) <> Тип("Число") Тогда
        ВызватьИсключение "Обе прочитанные native границы должны быть числами";
    КонецЕсли;
    Если Нижняя <> Цел(Нижняя) Или Верхняя <> Цел(Верхняя)
        Или Нижняя < 0 Или Нижняя > 65535 Или Верхняя < 0 Или Верхняя > 65535 Или Нижняя > Верхняя Тогда
        ВызватьИсключение "Нужны целые границы 0..65535 в правильном порядке";
    КонецЕсли;
    Если Нижняя <> ОжидаемаяНижняя Или Верхняя <> ОжидаемаяВерхняя Тогда
        ВызватьИсключение "Не совпало полное ожидаемое состояние своего диапазона; продолжение запрещено";
    КонецЕсли;
    Возврат Новый ФиксированнаяСтруктура("Нижняя,Верхняя", Нижняя, Верхняя);
КонецФункции

Функция РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, НижняяВторого, ВерхняяВторого,
    ОжидаемоеОбъединение, ОжидаемоеПересечение)
    СнимокПервого = ПрочитатьСвойДиапазон85(Первый, 45410, 45419);
    СнимокВторого = ПрочитатьСвойДиапазон85(Второй, НижняяВторого, ВерхняяВторого);
    Если СнимокПервого.Нижняя <> ОригинальныйПервый.Нижняя Или СнимокПервого.Верхняя <> ОригинальныйПервый.Верхняя
        Или СнимокВторого.Верхняя - СнимокВторого.Нижняя + 1 > 12 Тогда
        ВызватьИсключение "Исходный диапазон A изменен либо диапазон B перестал быть собственным маленьким планом";
    КонецЕсли;
    ПервыйПлан = Новый Массив;
    ВторойПлан = Новый Массив;
    ОбъединенныйПлан = Новый Массив;
    Для НомерПорта = СнимокПервого.Нижняя По СнимокПервого.Верхняя Цикл
        ПервыйПлан.Добавить(НомерПорта);
        ОбъединенныйПлан.Добавить(НомерПорта);
    КонецЦикла;
    Пересечение = 0;
    Для НомерПорта = СнимокВторого.Нижняя По СнимокВторого.Верхняя Цикл
        ВторойПлан.Добавить(НомерПорта);
        Если ПервыйПлан.Найти(НомерПорта) <> Неопределено Тогда
            Пересечение = Пересечение + 1;
        КонецЕсли;
        Если ОбъединенныйПлан.Найти(НомерПорта) = Неопределено Тогда
            ОбъединенныйПлан.Добавить(НомерПорта);
        КонецЕсли;
    КонецЦикла;
    Если ПервыйПлан.Количество() <> 10 Или ВторойПлан.Количество() <> СнимокВторого.Верхняя - СнимокВторого.Нижняя + 1
        Или ОбъединенныйПлан.Количество() <> ОжидаемоеОбъединение Или Пересечение <> ОжидаемоеПересечение Тогда
        ВызватьИсключение "Собственный расчет по actual readback не совпал с контрольными числами";
    КонецЕсли;
    Возврат Новый ФиксированнаяСтруктура("Объединение,Пересечение,КоличествоВторого",
        ОбъединенныйПлан.Количество(), Пересечение, ВторойПлан.Количество());
КонецФункции

Функция ВыполнитьСвойПлан85() Экспорт
    ПроверитьСвойСтенд85();
    Первый = Новый АдминистрированиеДиапазонПортов(45410, 45419);
    Второй = Новый АдминистрированиеДиапазонПортов(45420, 45429);
    ОригинальныйПервый = ПрочитатьСвойДиапазон85(Первый, 45410, 45419);
    До = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45420, 45429, 20, 0);
    Если До.КоличествоВторого <> 10 Тогда
        ВызватьИсключение "Исходный собственный B должен содержать десять чисел планировщика";
    КонецЕсли;
    Второй.НижняяГраница = 45418;
    ПослеНижней = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45429, 20, 2);
    Если ПослеНижней.КоличествоВторого <> 12 Тогда
        ВызватьИсключение "После первого setter читаем оба actual bounds: промежуточный B содержит двенадцать чисел";
    КонецЕсли;
    Второй.ВерхняяГраница = 45427;
    ПослеИзменения = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45427, 18, 2);
    Если ПослеИзменения.КоличествоВторого <> 10 Тогда
        ВызватьИсключение "После двух setter новый B снова содержит десять чисел";
    КонецЕсли;
    ПередВосстановлением = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45427, 18, 2);
    Если ПередВосстановлением <> Неопределено Тогда
        Если ПередВосстановлением.КоличествоВторого <> 10 Тогда
            ВызватьИсключение "Восстановление разрешено только после полного ожидаемого собственного состояния";
        КонецЕсли;
    Иначе
        ВызватьИсключение "Нет результата полной проверки перед восстановлением";
    КонецЕсли;
    Второй.ВерхняяГраница = 45429;
    ПослеВерхней = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45429, 20, 2);
    Если ПослеВерхней.КоличествоВторого <> 12 Тогда
        ВызватьИсключение "Промежуточное восстановление верхней границы не подтверждено";
    КонецЕсли;
    Второй.НижняяГраница = 45420;
    ПослеВосстановления = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45420, 45429, 20, 0);
    Если ПослеВосстановления.КоличествоВторого <> 10 Тогда
        ВызватьИсключение "Полный исходный собственный B не восстановлен";
    КонецЕсли;
    ФинальныйПервый = ПрочитатьСвойДиапазон85(Первый, 45410, 45419);
    Если ФинальныйПервый.Нижняя <> ОригинальныйПервый.Нижняя Или ФинальныйПервый.Верхняя <> ОригинальныйПервый.Верхняя Тогда
        ВызватьИсключение "Полный исходный snapshot A должен остаться неизменным";
    КонецЕсли;
    Возврат Новый ФиксированнаяСтруктура("До,Изменено,Восстановлено,ПересечениеДо,ПересечениеИзменено,ПересечениеВосстановлено,НижняяA,ВерхняяA",
        До.Объединение, ПослеИзменения.Объединение, ПослеВосстановления.Объединение,
        До.Пересечение, ПослеИзменения.Пересечение, ПослеВосстановления.Пересечение,
        ФинальныйПервый.Нижняя, ФинальныйПервый.Верхняя);
КонецФункции
Полный модуль своей формы: скалярный результат и две границы остановки

Общие → Общие формы → ПроверкаДиапазонов85 → Модуль

Толстый управляемый клиент и сервер своей формы, отдельные директивы контекста

&НаКлиенте
Процедура Выполнить85(Команда)
#Если ТолстыйКлиентУправляемоеПриложение Тогда
    Если Остановка85 Или Завершено85 Или ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Выполнить85 Тогда
        ВызватьИсключение "Только один запуск своей команды; повтор после ошибки или успеха запрещен";
    КонецЕсли;
    Попытка
        ВыполнитьНаСервере85();
        Если Не Завершено85 Или До85 <> 20 Или Изменено85 <> 18 Или Восстановлено85 <> 20
            Или ПересечениеДо85 <> 0 Или ПересечениеИзменено85 <> 2 Или ПересечениеВосстановлено85 <> 0
            Или НижняяA85 <> 45410 Или ВерхняяA85 <> 45419 Тогда
            ВызватьИсключение "Не подтвержден полный скалярный результат собственного memory расчета";
        КонецЕсли;
    Исключение
        Остановка85 = Истина;
        Протокол85 = "Отказ. Возможен частично измененный только свой memory B; повтора и слепого восстановления нет.";
        ВызватьИсключение;
    КонецПопытки;
#Иначе
    ВызватьИсключение "Только собственный толстый управляемый клиент";
#КонецЕсли
КонецПроцедуры

&НаСервере
Процедура ВыполнитьНаСервере85()
    Если Остановка85 Или Завершено85 Тогда
        ВызватьИсключение "Серверная граница также запрещает повтор";
    КонецЕсли;
    Попытка
        Пакет = ПланДиапазоновПамять85.ВыполнитьСвойПлан85();
        Если Пакет.До <> 20 Или Пакет.Изменено <> 18 Или Пакет.Восстановлено <> 20
            Или Пакет.ПересечениеДо <> 0 Или Пакет.ПересечениеИзменено <> 2 Или Пакет.ПересечениеВосстановлено <> 0
            Или Пакет.НижняяA <> 45410 Или Пакет.ВерхняяA <> 45419 Тогда
            ВызватьИсключение "Не совпали все восемь scalar результатов реального server readback";
        КонецЕсли;
        До85 = Пакет.До;
        Изменено85 = Пакет.Изменено;
        Восстановлено85 = Пакет.Восстановлено;
        ПересечениеДо85 = Пакет.ПересечениеДо;
        ПересечениеИзменено85 = Пакет.ПересечениеИзменено;
        ПересечениеВосстановлено85 = Пакет.ПересечениеВосстановлено;
        НижняяA85 = Пакет.НижняяA;
        ВерхняяA85 = Пакет.ВерхняяA;
        Протокол85 = "План с включенными границами: объединение20→18→20, пересечение0→2→0. A неизменен. Доступность портов и настройки сервера не проверялись.";
        Завершено85 = Истина;
    Исключение
        Остановка85 = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
Штатное startup событие открывает только собственную форму

Конфигурация → Открыть модуль управляемого приложения

Толстый клиент, управляемое приложение

Процедура ПриНачалеРаботыСистемы()
#Если ТолстыйКлиентУправляемоеПриложение Тогда
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnPortRangePlanner85_d5827fb0-6c4a-4879-b9e8-73517ef85d6b\IB"";" Тогда
        ВызватьИсключение "Нужна только своя новая File CF этого урока; другой формат регистрации откажет";
    КонецЕсли;
    ОткрытьФорму("ОбщаяФорма.ПроверкаДиапазонов85", , , Истина);
#Иначе
    ВызватьИсключение "Только собственный толстый управляемый клиент 8.5.1.1343";
#КонецЕсли
КонецПроцедуры

Разбор по шагам

  1. До factories проверяем точную собственную среду. New(45410,45419) и New(45420,45429) создают новые частные объекты A и B. При чтении проверяем настоящий тип, обе границыЧисло, целочисленность, интервал0..65535, порядок и точное ожидаемое собственное состояние.

  2. Фиксированный snapshot A получаем из двух actual native свойств, а не из заранее собранного dummy объекта. Снова читаем A и B; перечисляем реальные границы с нашим правилом включения. Два массива10/10 дают объединение20 и пересечение0. Найти может вернуть индекс0: наличие проверяется сравнением сНеопределено, не truthiness.

  3. Сначала меняем нижнюю границу B на45418 и немедленно перечитываем ОБЕ границы обоих объектов. Промежуточный B45418..45429 имеет12 чисел, объединение20 и пересечение2. Только после этой полной проверки меняем верхнюю на45427: B10, объединение18, пересечение2.

  4. Перед восстановлением отдельно подтверждаем целиком A и измененный B45418..45427 с расчетом18/2. Только затем возвращаем верхнююB45429, проверяем обе границы и промежуточные12/20/2; возвращаем нижнюю45420 и вновь проверяем10/20/0. При ошибке на любом setter или readback выполнение прекращается: автоматического catch-rollback нет.

  5. В конце снова читаем обе native границы A и сравниваем с первоначальным фиксированным snapshot. Возвращаем шесть чисел расчета и две реальные границыA, не нативные объекты администрирования. Собственная форма принимает все восемь scalar значений только после проверки и запрещает повтор.

Как проверить результат

  1. Будущий ручной протокол: итоговые объединения20→18→20 и пересечения0→2→0; A неизменен45410..45419. Между отдельными setter обязательны два промежуточных B12, объединение20, пересечение2.

  2. Во всех шести расчетах читаются актуальные обе границы A/B. Прочитанные границы проверяются до циклов. Восстановление начинается только после нового полного собственного состояния18/2; catch не делает setters, retry или продолжение.

  3. Source/text/static native equality/contexts/readonly/arity/aliases и negative mutants проверяются отдельно от1С runtime. Здесь sockets/RAS/cluster operations/DBwrites/UI/runtime0.

Ожидаемый результат

Ожидаемый будущий ручной результат: восемь чисел20,18,20,0,2,0,45410,45419 и протокол собственной формы. Частные native A/B полностью проверены, A сохранен и B восстановлен после успешных проверок. Реальное выполнение1С здесь не проводилось.

На что обратить внимание

  1. Конструктор принимает два необязательных числа, но native справка не задает их default. Урок передает оба явно; не угадывает поведение пустого конструктора, дробных или перевернутых границ.

  2. НижняяГраница и ВерхняяГраница RW. Возможная частичная ошибка не атомарна; отсутствие catch rollback намеренное. Новые объекты существуют только внутри серверной функции и не являются снимками или ссылками реального рабочего сервера.

  3. Включение обеих границ — наша явно заданная математическая модель, не proof реальной политики распределения1С. Совпадение числа45418 в двух массивах не означает занятый или свободный TCP/UDP порт.

  4. Здесь нет АдминистрированиеСервера, подключения к RAS, перечисления кластеров, назначения портов, socket/bind, сетевого сканирования, ОС-команд, печати и сохранения системных настроек. Проверка своего File/user не является sandbox безопасности чужой CF.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.