d->m_stage=Uninitialized;
d->m_iface=ifc;
d->m_log=0;
+ connect(this,SIGNAL(webFinished()),this,SLOT(endQuery()));
}
WTransaction::WTransaction(const WTransaction&t)
:WHelper()
d->m_errtype=t.d->m_errtype;
d->m_iface=t.d->m_iface;
d->m_log=0;
+ connect(this,SIGNAL(webFinished()),this,SLOT(endQuery()));
}
WTransaction::~WTransaction()
return ret;
}
-QByteArray WTransaction::executeQuery(QString hreq,QByteArray data)
+void WTransaction::startQuery(QString hreq,QByteArray data)
{
QNetworkRequest req;
- //set up request
- QEventLoop loop(this);
- connect(this,SIGNAL(webFinished()),&loop,SLOT(quit()));
//find interface
WInterface *iface=WInterface::instance(d->m_iface);
if(!iface){
d->m_stage=Error;
d->m_errtype="_iface";
d->m_errstr=tr("interface not found");
- return QByteArray();
+ return;
}
//set target
QUrl url=iface->url();
req.setHeader(QNetworkRequest::ContentLengthHeader,QByteArray::number(data.size()));
req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-webobject; charset=UTF-8");
//send it (with body)
- QNetworkReply*rsp=iface->post(req,data);
+ d->m_rsp=iface->post(req,data);
+ //latest point of deletion: end of this transaction
+ d->m_rsp->setParent(this);
//log request
if(d->m_log){
d->m_log->setRequ(hd2str(rqpairs(req)),esc(data));
}
- //make sure response is deleted
- QObject rspown;
- rsp->setParent(&rspown);
//we are requesting now...
d->m_stage=Request;
-
- /////////////////////////////////////////////////////////////////////
- //start loop
- QTimer tmr;
- tmr.setSingleShot(true);tmr.start(iface->webTimeout()*1000);
- connect(&tmr,SIGNAL(timeout()),this,SLOT(webTimeout()));
- connect(rsp,SIGNAL(finished()),this,SLOT(webReady()));
- connect(rsp,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(webError()));
- loop.exec();
- tmr.stop();tmr.disconnect(SIGNAL(timeout()),this,SLOT(webTimeout()));
- /////////////////////////////////////////////////////////////////////
-
+ //schedule receiving
+ if(d->m_qtimeout.isNull()){
+ d->m_qtimeout=new QTimer(this);
+ connect(d->m_qtimeout,SIGNAL(timeout()),this,SLOT(webTimeout()));
+ }
+ d->m_qtimeout->setSingleShot(true);
+ d->m_qtimeout->start(iface->webTimeout()*1000);
+ connect(d->m_rsp,SIGNAL(finished()),this,SLOT(webReady()));
+ connect(d->m_rsp,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(webError()));
+
+}
+
+void WTransaction::endQuery()
+{
+ //sanity check
+ if(d->m_rsp.isNull())return;
+ d->m_rspdata=QByteArray();
+ //unschedule timeout
+ if(!d->m_qtimeout.isNull())
+ d->m_qtimeout->stop();
+ //delete response object when done here
+ QObject rspown;
+ connect(&rspown,SIGNAL(destroyed(QObject*)),d->m_rsp,SLOT(deleteLater()));
//process result
if(d->m_stage==Error && d->m_errtype=="_timeout"){
//it did not finish yet, caught a timeout.
- rsp->abort();
+ d->m_rsp->abort();
d->m_errstr=tr("Web Request timed out.");
if(d->m_log)d->m_log->setError("Request timed out.");
- return QByteArray();
+ return;
}else
//finished with low-level error?
if(d->m_stage==Error){
- d->m_errstr="HTTP Error: "+rsp->errorString();
+ d->m_errstr="HTTP Error: "+d->m_rsp->errorString();
if(d->m_log)d->m_log->setError(QString("Request finished with HTTP level error: %1").arg(d->m_errstr));
- return QByteArray();
+ return;
}
//get data
- d->m_wobstatus=rsp->rawHeader("X-WobResponse-Status");
+ d->m_wobstatus=d->m_rsp->rawHeader("X-WobResponse-Status");
d->m_wobstatus=d->m_wobstatus.replace("\"","").trimmed().toLower();
- QByteArray rspdata=rsp->readAll();
- if(d->m_log)d->m_log->setResp(hd2str(rsp->rawHeaderPairs()),esc(rspdata));
+ d->m_rspdata=d->m_rsp->readAll();
+ if(d->m_log)d->m_log->setResp(hd2str(d->m_rsp->rawHeaderPairs()),esc(d->m_rspdata));
//check for high level error
- int statcode=rsp->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ int statcode=d->m_rsp->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(statcode!=200){
- d->m_errstr=tr("HTTP Error, return code %1 %2") .arg(statcode).arg(rsp->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
+ d->m_errstr=tr("HTTP Error, return code %1 %2") .arg(statcode).arg(d->m_rsp->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
d->m_errtype="_HTTP";
d->m_stage=Error;
if(d->m_log)d->m_log->setError(QString("Request finished with HTTP level error: %1").arg(d->m_errstr));
- return QByteArray();
+ return;
}
if(d->m_stage==Request){
d->m_stage=Error;
d->m_errstr="Ooops: still in Request phase at end of response handling.";
}
//remaining high level errors are handled by the generated code
- return rspdata;
+}
+
+QByteArray WTransaction::executeQuery(QString hreq,QByteArray data)
+{
+ //set up request
+ startQuery(hreq,data);
+ if(d->m_rsp.isNull() || d->m_stage!=Request)
+ return QByteArray();
+
+ /////////////////////////////////////////////////////////////////////
+ //start loop
+ QEventLoop loop(this);
+ connect(this,SIGNAL(webFinished()),&loop,SLOT(quit()),Qt::QueuedConnection);
+ loop.exec();
+ /////////////////////////////////////////////////////////////////////
+
+ if(d->m_stage==Success)
+ return d->m_rspdata;
+ else
+ return QByteArray();
}
void WTransaction::webTimeout()
{
if(d->m_stage!=Request)return;
// qDebug("web timeout");
+ if(d->m_log)d->m_log->setInfo(QString("timeout in request"));
d->m_stage=Error;
d->m_errtype="_timeout";
emit webFinished();
QString WTransaction::interface()const{return d->m_iface;}
+static int logid=0;
+
WTransaction::Log::Log(WTransaction*p,const QString&s)
{
parent=p;
parent->d->m_log=this;
trn=s;
+ cnt=logid++;
WInterface*in=WInterface::instance(p->d->m_iface);
if(in)lvl=in->logLevel();
else lvl=WInterface::LogOnError;
if(lvl>WInterface::LogNone)
- qDebug("Running transaction %s",s.toAscii().data());
+ outStr(QString("Running transaction %1").arg(s));
}
WTransaction::Log::~Log()
parent->d->m_log=0;
}
+void WTransaction::Log::outStr(const QString&s)
+{
+ QStringList sl=s.split("\n");
+ for(int i=0;i<sl.size();i++)
+ qDebug("T%i: %s",cnt,sl[i].toAscii().data());
+}
+
void WTransaction::Log::setRequ(const QString&h,const QString&d)
{
if(lvl<=WInterface::LogInfo)return;
- QByteArray r="Request"
- "\n--Header--\n"+h.trimmed().toAscii()
- +"\n--Body--\n"+d.trimmed().toAscii()+"\n--End--";
+ QString r=QString("Transaction %1, Request:\n--Header--\n%2\n--Body--\n%3\n--End--")
+ .arg(trn).arg(h).arg(d);
if(lvl==WInterface::LogDetailed)
- qDebug("Transaction %s request: %s",trn.toAscii().data(),r.data());
+ outStr(r);
else
if(lvl==WInterface::LogOnError)
req=r;
void WTransaction::Log::setResp(const QString&h,const QString&d)
{
if(lvl<=WInterface::LogInfo)return;
- QByteArray r="Response"
- "\n--Header--\n"+h.trimmed().toAscii()
- +"\n--Body--\n"+d.trimmed().toAscii()+"\n--End--";
+ QString r=QString("Transaction %1, Response:\n--Header--\n%2\n--Body--\n%3\n--End--")
+ .arg(trn).arg(h).arg(d);
if(lvl==WInterface::LogDetailed)
- qDebug("Transaction %s response: %s",trn.toAscii().data(),r.data());
+ outStr(r);
else
if(lvl==WInterface::LogOnError)
rsp=r;
void WTransaction::Log::setInfo(const QString&s)
{
if(lvl>=WInterface::LogInfo)
- qDebug("Transaction %s info: %s",trn.toAscii().data(),s.toAscii().data());
+ outStr(QString("Transaction %1 info: %2").arg(trn).arg(s));
}
void WTransaction::Log::setError(const QString&s)
if(lvl<WInterface::LogMinimal)return;
//only for LogOnError, these have been stored, replay them:
if(req.size()>0){
- qDebug("Transaction %s on error, request was: %s",trn.toAscii().data(),req.data());
+ outStr(req);
req=QByteArray();
}
if(rsp.size()>0){
- qDebug("Transaction %s on error, response was: %s",trn.toAscii().data(),rsp.data());
+ outStr(rsp);
rsp=QByteArray();
}
//show actual error
- qDebug("Transaction %s Error: %s",trn.toAscii().data(),s.toAscii().data());
+ outStr(QString("Transaction %1 Error: %2").arg(trn).arg(s));
}
\ No newline at end of file