powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Время исполненя процедуры.
15 сообщений из 15, страница 1 из 1
Время исполненя процедуры.
    #33160947
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Задача проста, нужно выполнить запрос вначале на удаленном сервере и если он не доступен, то на локальном. Я написал extended stored procedures, которая выполняет запрос на удаленном сервере. Но самое проблематичное то, что нужно четко выдержать время запроса (не более 5 секунд). По истечении данного времени, нужно уже тянуть данные с локального сервера. Я создал OLEDB класс и выполняю хронимку в отдельном треде, ожидая его завершения в течении 5 секунд. Выставить таймауты на соединение и выполнение команды не составляет труда, трудности возникают при обрыве канала. В этом случае время ожидания достигает уже нескольких минут. Если я завершаю работу треда, то получаю зависшие конекшены на серваке. Может, кто уже решал такую же задачу?
Спасибо!
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33161107
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Напрашиваеться работа в отдельном потоке с БД. И связь с основным через синхро обьекты. Ожидание на синхро обьекте может быть регламентирована "временем ожидания".


вроде то что пришло на ум.
(круглый)
ЗЫ
На мой взгляд - в консерватории проблемы.
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33161194
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обнаружение разрыва соединения зависит целиком от используемых сетевых библиотек (TCP/IP, IPX/SPX и т.д.). Например, в TCP есть специально настраиваемый time-out, после достижения которого соединение считается разорванным.
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33161195
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну вот выдержки из кода:

Вызывающая функция:
RETCODE __declspec(dllexport) xp_mirCheckForNewCardinOffice(SRV_PROC *srvproc)
{
try
{
ExecProc pProc(srvproc);
return(pProc.Run());
}
catch(...)
{
DBCHAR ErrorMsg[255];
DBINT ErrorID;
ErrorID = SQL_EXEC_ERROR;
sprintf(ErrorMsg, "Error executing procedure: Error executing procedure.");
srv_paramsetoutput(srvproc, 8, (BYTE*)&ErrorID, sizeof(DBINT), FALSE);
srv_paramsetoutput(srvproc, 9, (BYTE*)ErrorMsg, 255, FALSE);
srv_senddone(srvproc, SRV_DONE_MORE | SRV_DONE_COUNT, (DBUSMALLINT)0, (DBINT)0);
}
return XP_NOERROR;
}

Рабочий сласс:
public:
Csp_mirCheckForNewCardInOffice m_CheckForNew;

RETCODE ExecProc::Run()
{
unsigned threadID;
hTh = (HANDLE)_beginthreadex( NULL, 0, &Start, this, 0, &threadID );

switch (dw)
{
case WAIT_OBJECT_0: // процесс завершается
if(this->ErrorID != XP_NOERROR && srvproc != NULL)
err_handler(ErrorID, ErrorMsg, srvproc);
else
{
ReturnResult();
}
break;
case WAIT_TIMEOUT: // процесс не завершился в течение TimeOut
// TerminateThread(hTh, 0);
ErrorID = TIME_OUT_EXPIRED;
sprintf(ErrorMsg, "Error executing procedure: Time out expired. Function break.");
err_handler(ErrorID, ErrorMsg, srvproc);
break;
case WAIT_FAILED: // неправильный вызов функции (неверный описатель?)
ErrorID = ERROR_PROC_EXEC;
sprintf(ErrorMsg, "Error executing procedure: Error start extended stored procedure.");
err_handler(ErrorID, ErrorMsg, srvproc);
break;
}
}
}

ExecProc::~ExecProc(void)
{
if(hTh != NULL)
{
WaitForSingleObject(hTh, INFINITE);
CloseHandle(hTh);
this->m_CheckForNew.CloseAll();
}
}

unsigned __stdcall Start(void *arg)
{
ExecProc* _this = static_cast<ExecProc*>(arg);
try
{
HRESULT hr = _this->m_CheckForNew.OpenAll();
if (FAILED(hr))
{
_this->ErrorID = _this->m_CheckForNew.ErrorId;
sprintf(_this->ErrorMsg, _this->m_CheckForNew.ErrorMsg.c_str());
}
}
catch(...)
{
_this->ErrorID = SQL_EXEC_ERROR;
sprintf(_this->ErrorMsg, "Error executing procedure: Error executing procedure.");
}
_endthreadex(0);
return 0;
}

Класс БД(После визарда, почти ничего не менял):

class Csp_mirCheckForNewCardInOffice : public CCommand<CAccessor<Csp_mirCheckForNewCardInOfficeAccessor>, CNoRowset >
{
public:
std::string ErrorMsg;
long ErrorId;
Csp_mirCheckForNewCardInOffice()
{
ErrorMsg = "";
ErrorId = 0;
}
public:
HRESULT OpenAll()
{
HRESULT hr;
hr = OpenDataSource();
if (FAILED(hr))
{
this->CheckOLEDBError(hr);
return hr;
}
__if_exists(GetRowsetProperties)
{
CDBPropSet propset(DBPROPSET_ROWSET);
__if_exists(HasBookmark)
{
propset.AddProperty(DBPROP_IRowsetLocate, true);
}
GetRowsetProperties(&propset);
return OpenRowset(&propset);
}
__if_not_exists(GetRowsetProperties)
{
__if_exists(HasBookmark)
{
CDBPropSet propset(DBPROPSET_ROWSET);
propset.AddProperty(DBPROP_IRowsetLocate, true);
return OpenRowset(&propset);
}
}
return OpenRowset();
}

HRESULT OpenRowset(DBPROPSET *pPropSet = NULL)
{

try
{
HRESULT hr = Open(m_session, NULL, pPropSet);
if(FAILED(hr))
this->CheckOLEDBError(hr);
return hr;
}
catch(CAtlException &ex)
{
ErrorId = 60017;
ErrorMsg = "Error executing procedure: Error executing procedure.";
return ex.m_hr;
}
catch(...)
{
ErrorId = 60017;
ErrorMsg = "Error executing procedure: Error executing procedure.";
return FAIL;
}
}

void CloseAll()
{
Close();
ReleaseCommand();
CloseDataSource();
}

void CheckOLEDBError(HRESULT hr)
{
try
{
CDBErrorInfo myErrorInfo;
ULONG numRec = 0;
BSTR myErrStr,mySource;
ISQLErrorInfo *pISQLErrorInfo = NULL;
LCID lcLocale = GetSystemDefaultLCID();
myErrorInfo.GetErrorRecords(&numRec);
// ERRORINFO* ErrINFO;
if (numRec)
{
myErrorInfo.GetAllErrorInfo(0,lcLocale,&myErrStr,&mySource);
// myErrorInfo.GetBasicErrorInfo(0, ErrINFO);
ErrorMsg = (_bstr_t)(myErrStr);
if(ErrorMsg.find("Timeout expired") != std::string::npos)
ErrorId = 60016;
if(ErrorId == 0)
ErrorId = 60017;
if(ErrorMsg.length() > 7998)
ErrorMsg = ErrorMsg.substr(0, 7998);
}
}
catch(...)
{
ErrorId = 60017;
ErrorMsg = "Error executing procedure: Error executing procedure.";
}
}
};
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33161206
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivОбнаружение разрыва соединения зависит целиком от используемых сетевых библиотек (TCP/IP, IPX/SPX и т.д.). Например, в TCP есть специально настраиваемый time-out, после достижения которого соединение считается разорванным.

Так в MSDN я об этом читал... Только данный таймаут установить можно только на все соединения, а это в даннос случае не годиться, таймаут нужно настроить только для выполнения одного запроса и для определенного удаленного сервера, чего сделань нельзя, или я ошибаюсь...?
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33162158
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Slava SolovievТак в MSDN я об этом читал... Только данный таймаут установить можно только на все соединения, а это в даннос случае не годиться, таймаут нужно настроить только для выполнения одного запроса и для определенного удаленного сервера, чего сделань нельзя, или я ошибаюсь...?
Почему нельзя? Можно. Но это зависит от сервера. Если ты рвешь связь с сервером БД - мало прибить клиентский поток сделавший запрос. Надо послать на сервер команду отмены (причем не все сервера БД такую команду имеют). Потом закрыть коннект, и только потом прибивать поток.
После того как ты скомандуешь серверу отменить запрос - сервер начнет делать rollback и в зависимости от сложности запроса информация о коннекте будет еще некоторое время висеть в списке коннектов на сервере.
А вот если ты все это учтешь - задача станет действительно очень простой :)
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33162173
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl Slava SolovievТак в MSDN я об этом читал... Только данный таймаут установить можно только на все соединения, а это в даннос случае не годиться, таймаут нужно настроить только для выполнения одного запроса и для определенного удаленного сервера, чего сделань нельзя, или я ошибаюсь...?
Почему нельзя? Можно. Но это зависит от сервера. Если ты рвешь связь с сервером БД - мало прибить клиентский поток сделавший запрос. Надо послать на сервер команду отмены (причем не все сервера БД такую команду имеют). Потом закрыть коннект, и только потом прибивать поток.
После того как ты скомандуешь серверу отменить запрос - сервер начнет делать rollback и в зависимости от сложности запроса информация о коннекте будет еще некоторое время висеть в списке коннектов на сервере.
А вот если ты все это учтешь - задача станет действительно очень простой :)

Я не смог найти команду отмены запроса в OLEDB... Не подскажешь ???
Использую MSSQL2000.
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33162177
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да и еще забыл сказать, как я пошлю команду отмены, если канала нет ???
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33162224
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не понятно что такое
switch(dw)


откуда прибежал ?
если это Вы делаете в цикле - 100% проца Вам обеспечено.
И ещё...
1) Нет контроля (возможно опущен) подьёма нитки. Фаза СИНХРОННАЯ и должна контролироваться. В противном случае при ударной нагрузке может выполняться не в той последовательности, чем при спокойном режиме.
2) Между потоком и основной ниткой заводите синхро обьект. Либо ждёте на хэндлере самого потока (возможно так и есть - не вижу просто) определённое время.
3) Выше уже подсказали механизацию "убийств" со стороны сервака. Думаю Вам придёться открывать для этого ышо один коннект. Это в случае когда сервак жив.
4) Думаю если сервак труп - то молчать будут и другие службы. Например ICMP.

удачи вам
(круглый)
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33162269
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Slava SolovievЯ не смог найти команду отмены запроса в OLEDB... Не подскажешь ???
ICommand::Cancel() наверное, ни разу в жизни не работал с OLE DB из С, так что могу и ошибиться :)
В ODBC есть функция SQLCancel(), в ADO у объектов делающих запросы есть метод Cancel().

Slava SolovievИспользую MSSQL2000.
Значит идешь в форум где тусуются любители MSSQL2000 и спрашиваешь у них как сервер ведет себя при отмене последней недовыполненой команды. Как он ведет себя при закрытии коннекта к серверу без отмены недовыполненной команды. Как он ведет себя в случае довыполнения команды, но обрывом связи клиентом без коммита. Это все вопросы первоочередной важности. Их надо знать на зубок.

Slava SolovievДа и еще забыл сказать, как я пошлю команду отмены, если канала нет ???
Если канала уже нет, то никак конечно же. Тогда только молится что сервер правильно обработает пропадание клиента. Но по хорошему, ты все же сначала должен скомандовать серверу отмену, потом закрыть коннект, и только потом убивать процесс.
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33162857
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
после вырубания клиента (напр. по 3 клавишам) на сервере начинается откат транзакции до полного его завершения.
2. Непонятна постановка:
- если сервер не доступен то это проверяется простой процедурой SELECT CONNECT.
- не доступен из-за загрузки его - не определишь.
============
Тогда в чём проблема?
============
ЗЫ.
поиск по KILL на форуме сиквела
http://www.sql.ru/forum/actualtopics.aspx?search=kill+&bid=1
______________________________________________
Вы имеете право хранить молчание! Всё что Вы скажете может быть использовано против Вас в суде!
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33163162
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kolobok0не понятно что такое
switch(dw)


откуда прибежал ?
если это Вы делаете в цикле - 100% проца Вам обеспечено.
И ещё...
1) Нет контроля (возможно опущен) подьёма нитки. Фаза СИНХРОННАЯ и должна контролироваться. В противном случае при ударной нагрузке может выполняться не в той последовательности, чем при спокойном режиме.
2) Между потоком и основной ниткой заводите синхро обьект. Либо ждёте на хэндлере самого потока (возможно так и есть - не вижу просто) определённое время.
3) Выше уже подсказали механизацию "убийств" со стороны сервака. Думаю Вам придёться открывать для этого ышо один коннект. Это в случае когда сервак жив.
4) Думаю если сервак труп - то молчать будут и другие службы. Например ICMP.

удачи вам
(круглый)

ой, пардон, забыл :) switch(dw) Вобщем читать так :
unsigned threadID;
hTh = (HANDLE)_beginthreadex( NULL, 0, &Start, this, 0, &threadID );
DWORD dw = WaitForSingleObject(hTh, this->TimeOut * 1000);
switch(dw)
{
case WAIT_OBJECT_0: // процесс завершается
case WAIT_TIMEOUT: // процесс не завершился в течение TimeOut
case WAIT_FAILED: // неправильный вызов функции (неверный описатель?)
}
Это ожидание завершение процесса....
по пункту 3 - Видимо да, хотя не очень бы хотелось...
по пункту 4 - Если не сложно, то может у вас есть класс дя пинга по ICMP...
Спасибо.
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33163214
Slava Soloviev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Petro123
- если сервер не доступен то это проверяется простой процедурой SELECT CONNECT.

А можно об этом поподробнее...
Спасибо.
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33163257
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Slava Soloviev Petro123
- если сервер не доступен то это проверяется простой процедурой SELECT CONNECT.

А можно об этом поподробнее...
Спасибо.
даёшь запрос:
Код: plaintext
SELECT  1 
, если сервер жив, то в ADO не будет исключалки (ошибки) и вернётся пустой набор. Иначе будет исключительная ситуация при обработке которой ты можешь:
- послать по мылу сообщение.
- материться матом на уборщицу за швабру.
- запустить таймер на реконнект всех открытых таблиц.
- ..........
...
Рейтинг: 0 / 0
Время исполненя процедуры.
    #33163268
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pkarklin ............Ну, если автоматом делать реконнект, то можно и так. У меня просто м меню Сервис есть пункт Восстановить подключение, которое и выбирает пользователь, если коннект разорвался, а такое бывает редко.
______________________________________________
Вы имеете право хранить молчание! Всё что Вы скажете может быть использовано против Вас в суде!
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Время исполненя процедуры.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]