<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
Файл в таком случае нужно располагать на сетевом ресурсе, доступном со всех рабочих серверов. Либо нужно при начале сеанса проверять, что количество рабочих серверов кластера = 1, иначе выбрасывать исключение.
Еще кажется очень неплохим дополнением было бы указать, как экономичнее всего ждать на мьютексте.
а .ОжидатьЗавершения() у ФЗ не то же самое делает?
(1) tormozit, каталог временных файлов доя rphosrов одного сервера обычно один. Если же рабочие процессы разнесены по разным серверам, то в случае подключения ВК на другом сервере rphost умереть не должен — это ведь другая система.
(2) vano-ekt, Вы просто не поняли, о чем речь. Это поправимо.
мм.. а если этот рпхост упадет после установки блокировки — она упадет или останется установленной?
(3) статья же не про мьютекс создания внешней компоненты, а в общем про мьютекс. Или я не понял статью?
(5) AlX0id, здесь блокировка создается за счет «захвата» текстового файлового потока. Пока он не закрыт — блокировка сохраняется. При том файлами управляет ОС. Если процесс ОС умирает, то ОС освобождает файл. Вот если rphost зависнет — вот тут блокировка сохранится.
У нас статистика накоплена, т.к. я после неудачной попытки установить блокировку пишу сообщение в журнал регистрации. Так вот на 20 тысяч печатных форм, формирующихся и пишущихся в PDF-файл на шары CUPS-серверов, неудачных блокировок где-то в районе двух десятков — меньше 0,1%. Случаев сбоя работы файловых блокировок я не наблюдал ни разу за примерно полгода использования. А вот случаи смерти rphosta без этих блокировок наблюдал ежедневно на протяжении еще полугода, пока механизм блокировок не был реализован.
(6) tormozit, статья про мьютекс, но в качестве примера приведен именно механизм монопольного выполнения участка кода при многопоточном выполнении операций (что, собственно, и делает сервер 1С).
(8) в общем достаточно признать, что я сделал справедливое замечание =)
(8) все таки я не понял ответов на вопросы заданные tormozit 1) что будет если код не дойдет до строки файлБлокировки.Закрыть(); (точнее понятно . что ничего хорошего) 2) есть ли варианты снизить нагрузку Пока НЕ СоздатьБлокировку(«ПечатьШтрихКода», файлБлокировки) Цикл , поскольку это однозначно нагружает CPU. хотя я понимаю, что оба вопросы скорее вопросы к несовершенству возможностей 1С. (1) tormozit,
при таком подходе имхо безопаснее все же сделать через БД , либо через какую-нибудь таблицу флагов прямо в БД, либо используя возможности , предоставляемые БД.
(11) cool.vlad4, пустой цикл однозначно гнать не стоит. при большом количестве потоков и более-менее длительном коде внутри блокировки получим печку вместо проца.
хорошо бы использовать что-то, что альтернативно нагружает проц… хотя бы тот же КомандаСистемы(«ping localhost»)
(11) cool.vlad4, (12) nixel,
ответ на певый вопрос см в (7)
а ответ на 2) гонять цикл это конечно бред. Достаточно использовать обработчик ожидания
(13) dabu-dabu, да, не увидел. в последнее время читаю между строк, все время тороплюсь)
В многопоточном замере производительностиhttp://infostart.ru/public/173394/ в качестве мьютекса используется управляемая блокировка на константу. Сначала на константу вешается исключительная блокировка, потоки выполнения пытаются повесить разделяемую блокировку и ждут, пока «управляющий» поток снимет исключительную блокировку. Конечно, у этолго способа куча ограничений, но использовать его можно.
В составе теста есть обработка «проверка синхронизации», которая показывает, за какое время (от момента снятия исключительной блокировки) фоновые задания принимают сигнал о её снятии.
(11),(15) Управляемая транзакционная блокировка может удерживаться естественно только в рамках транзакции. А долгие транзакции не есть хорошо. Поэтому блокировка файла выглядит более корректным способом.
(16) tormozit, Я не говорю, что этот способ идеальный. Как раз его ограничение в том, что снимается блокировка именно по окончанию транзакции. Это влечет принципиальную невозможность использования такого способа если сами «многопоточные потоки» или их родители выполняются в транзакции.
А сами по себе долгие транзакции (если в них блокируется только ресурс-мьютекс) почти никаких доп. нагрузок не вносят.
Ну и время ожидания блокировки надо подбирать соответствующее и хотя бы временно его выставлять (как делается в тесте).
(17)
Ну не совсем так. Они удерживают соединения с СУБД. Если их будет много и долго, то будет нехорошо. Признаюсь, я сам не вполне понимаю, в чем заключается это «нехорошо», но так меня учили =)
(13) dabu-dabu, да, гонять цикл нехорошо, но какие есть альтернативы? Может быть когда-нибудь 1С сделает sleep, но пока я лично не знаю, как реализовать его на 1С. Есть вариант вызова пинга, но он секунду ждет — за секунду у меня пять форм печатных формируется и в файлы пишется (!)
Когда блокировка устанавливается на минимальное время, то сама попытка открытия файла на запись уже выполняется достаточное время, чтобы во второй-третьей итерации цикла дождаться снятия предыдущей блокировки. Все остальное время сервер тоже выполняет код. Но имейте ввиду, что тут не пустой цикл гоняется, в открывается текстовой поток на запись — это I/O, в механизме которого слипов, поверьте, достаточно, чтобы оставить ваш процессор чуть тепленьким.
(19) Есть замечательная функция ПодключитьОбработчикОжидания, о чем я и писал в (13)
(7)
Сначала подумал, что останется висеть, потом так и решил, да — хотел убедиться )
(20) dabu-dabu, а эту замечательную функцию можно применить на сервере или во внешнем соединении?
(20) dabu-dabu, и как он работает на сервере?
Очень был удивлён…
1) Мьютекс это сущность внутри ОС Windows и никак не относится к языку программирования
2) Многопоточность конечно
3) Многопоточность это тоже в принципе относится к ОС, может к приложению но весьма отдалённо к языку программирования
4) Ну и 1С — это не язык программирования…
Ну и конечно запись текста вместо мьютекса можно вообще оставить без комментариев. Нужен мьютекс — используйте мьютекс.
http://infostart.ru/public/76974/ или http://infostart.ru/public/18636/
Если лениво свою ВК писать воспользуйтесь:
Хотя приведённая задача решается совсем другим способом.
(24) comol,
https://ru.wikipedia.org/wiki/Green_threads . хотя согласен, что к 1С это малоприменимо.
1) в узком смысле, да. в широком смысле это один из паттернов синхронизации. т.о. относится не только к ОС.
3) потоки бывают не только уровня ОС. см
4) язык программирования, Тьюринг полный. на нем гипотетически и ВМ можно написать. просто оно никому не надо…(уточню, что гипотетически))) )
(24) comol, Ваш комментарий не полезен, но интересен:
1) «Мью́текс (англ. mutex, от mutual exclusion — «взаимное исключение») — аналог одноместного семафора, служащий в программировании для синхронизации одновременно выполняющихся потоков.» (с) Словарь.
Отсюда мораль: не знаете — не говорите. То, что мьютекс реализован в API системы, никак не меняет дело. Поэтому реализация принципа мьютекса без танцев с бубном вокруг WinAPI не является моветоном — это лишь одна из реализаций принципа.
2) «Много» и «Мульти» — это синонимы. «лат. multi-, от multus многий, многочисленный) — составная часть сложных слов, означающая…» (с) Словарь. Учитесь пользоваться словарем, чтобы распознать тезаурус сообщения, если не знаете слов.
3) Тоже весьма спорный тезис, но в общем и целом условно верный. Различие лишь в том, что для одних языков существуют библиотеки с реализацией данного механизма, а для других — нет. В 1С реализация есть, но про блокировки как-то забыли, иначе не пришлось бы критический код подключения внешней компоненты блокировать, чтобы rphost не умер. Или Вы считаете, что в сказку попали?
4) 1С — это среда, как и Delphi, например. Там язык программирования Pascal, а тут какой?
Вообще, я удивлен Вашим ответом. Он не несет пользы. Вот если бы Вы указали, что мьютекс можно реализовать с помощью WinAPI так-то и так-то — это было бы, возможно, кому-то полезно.
(25) cool.vlad4,
1 и 2 Ладно, не уровня ОС, но не в языке программирования же???
4 интересный вопрос чем ЯП отличается от Framework… по-моему 1С это Framework
(27) comol, фрэймворк — это Эклипс. надеюсь, что осталось уже не долго до того светлого дня, когда 1С туда переедет. Как будет называться язык?
(27) comol, 4. не, интересный вопрос, библиотека vs фрэймворк , либо язык общего назначения vs язык специального назначения (dsl) . 1С это язык тем не менее общего назначения (хотя в нем есть элементы dsl , например язык запросов это dsl) + вшитый наглухо фрэймворк от производителя. фрэймворк это библиотека с некоторыми правилами и экосистемой, без которой ничего сделать не получится в рамках этой библотеки. (т.е. имхо фрэймворк это некоторая спецификация библиотек или систем библиотек, влияющая на архитектуру, на стиль кодирования и т.п.)
(27) comol, а по поводу многопоточности и системы, то, поверьте, в DOS вполне можно было реализовать многопоточность, переключаемую прерыванием таймера. RTOS (http://easyelectronics.ru/tag/rtos) , выполняясь на одноядерном микропроцессоре, тоже позволяет использовать несколько потоков. А можно и без RTOS обойтись — запрограммировать тот же микроконтроллер иначе, получив тот же функционал.
Таким образом получается вывод следующий: там, где ОС не предусматривает многопточность, ее все-равно можно реализовать.
(26) Оу оу…
Вы бы не меня учили а сами хоть научились…
1) Речь о том что мьютекс не сущность языка программирования, как вы там написали…
«Танцы с бубном вокрог API» пишутся в 3 строчки кода:
Wrap = CreateObject(«DynamicWrapperX»);
Wrap.Register(«KERNEL32.DLL», «CreateMutex», «i=pls», «r=l»);
hMutex = Wrap.CreateMutex(0, 0, «MyMutex»);
естественно с использованием ВК, к примеру отсюда:http://infostart.ru/public/267819/
Я думаю это не тема статьи или ещё чего-либо
2) только все говорят «многопоточность», ну кроме тех кто впервые этот термин использует
Вцелом низачет конечно… причём не в переносном смысле а скорее по
школьнойинститутской программе…(31) comol, а я в институтах не учился — академиком родился )))
Но это не отменяет того, что русский язык Вы знаете хорошо, а латынью не владеете. Но тут, конечно, уже институтской программы маловато будет. особенно в современном ее виде.
Если говорить о сущностях, то и файл не является сущностью языка, и поток, и многопоточность — это частные случаи реализации механизмов хранения и обработки данных.
Если говорить об API, то Ваш функционал, полагаю, будет неплохо работать в среде Windows, а мой функционал в принципе кросспатформенный, и позволяет реализовать нужное мне поведение системы.
В заключение: если Вы претендуете на исключительное владение темой, то напишите статью — кто ж Вам мешает? Но из того, что Вы тут понаписали, толку чуть меньше, чем нисколько…
(29) cool.vlad4, (28) Ну вообще 1С сама себя считает фреймворком:http://v8.1c.ru/eng/the-platform/in-generalarchitecture.htm я тоже придерживаюсь этого мнения… а эклипс я всю жизнь думал что это IDE…
(30) даже не спорю… даже где нет ОС её можно организовать 😉
(32) Ну разобрались это уже хорошо. Значит не совсем всё бес толку что я написал… 🙂
(33) comol, в смысле? не увидел противоречий. я же выше написал, что 1с это язык + фрэймворк. по твоей ссылке нигде не написано, что это не так. а фраза 1C Virtual Machine какбэ еще и намекает.(просто фрэймворком 1С был бы , если предназначался для другого языка. просто фрэймоврк в вакууме без языка, такого не бывает, comol ))) )
(33) comol, возможно он имеет ввиду eclipse rich client platform . как бы с eclipse тоже не все так просто)
(33) comol, силился вспомнить, что из rcp образного использовал. например rssowl (страшно глючный кстати) сделан на eclipse rcp
А кто-нибудь скажет мне, чем фреймворк отличается от IDE, и что из этого ближе к 1С? ))) Да, определения погуглите предварительно.
(39) фреймворк — код( возможно библиотеки)
IDE — инфраструктура для редактирования и сборки кода…
утрированно:
с IDE — работает только программист
с фреймворком — работают пользователи (неявно используют)
1С — запускается в разных режимах. В режиме разработчика — IDE. В режиме предприятия — фреймворк.
(40) minimajack, ну почти правильно. IDE — это, если перевести, интегрированная среда разработки. В принципе, конфигуратор — это IDE. Фреймворк — это совокупность библиотек, каркас решения. К фреймворкам, например, относится QT, .NET. В 1С к фреймворкам можно отнести непосредственно решения, например, ERP. Ведь программист на базе решения зачастую что-то свое вносит. Так что, полагаю, кто-то реально путает понятия.
(24) comol, предложенное решение выгодно отличается тем, что это не всякие сомнительные ВК, которые ещё регистрировать везде надо, а нормальный штатный код 1С. По сути мьютекс сделан.
А каким другим способом решается задача, если не секрет?
(42) Yashazz, ИМХО, некто под ником «comol» поспешил с выводом о том, что задача решается другим способом. Увы и ах…
(44). И что тут такого? В онлайн сервисах у нас десятки тысяч пользователей — и все работает.
(26) Вашу фразу — «Ваш комментарий не полезен, но интересен» сделала мне сегодня утро. Теперь я тоже буду толерантным :-)))
А я использую метод ЗаблокироватьДанныеДляРедактирования(), можно в качестве ключа передавать ключ регистра сведений, у которого измерение (например строковое) будет заполнено нужным значением, транзакция для такой блокировки не требуется.
Добрый день!
В вашей статье описан, по моему мнению, спинлок. Мьютекс — это если ваш код в момент запроса ресурса «засыпает», и просыпается когда ресурс становиться доступен, или обнаружена ошибка (блокировка, или долгое ожидание).
По поводу реализации синхронизации данных в нескольких потоках выполнения. Это может делать ОС, а может интерпретатор. Главное, иметь возможность управлять потоками выполнения. Например, посмотрите как реализованы примитивы синхронизации в Java.
(48) в 1С ничего для блокировки нет, кроме блокировок каких-то элементов в самой СУБД или блокировок файла. Фактически мьютекс описан так:
———
Задача мьютекса — защита объекта от доступа к нему других потоков, отличных от того, который завладел мьютексом. В каждый конкретный момент только один поток может владеть объектом, защищённым мьютексом. Если другому потоку будет нужен доступ к переменной, защищённой мьютексом, то этот поток блокируется до тех пор, пока мьютекс не будет освобождён.
Цель использования мьютексов — защита данных от повреждения в результате асинхронных изменений (состояние гонки), однако могут порождаться другие проблемы — например взаимная блокировка (клинч).
———-
Про засыпание других потоков ничего не сказано. Фактически второй поток, пытающийся обратиться к заблокированным данным, получает отказ, но операционная система не обязана усыпить поток до освобождения данных, ибо поток в это время может обрабатывать что-то другое, что не заблокировано. Для блокировки участка кода данный подход через файловую блокировку вполне оправдан.