From dc95cfa2c2c119558918de777ffb6f762401431a Mon Sep 17 00:00:00 2001 From: konrad Date: Thu, 30 Sep 2010 18:47:29 +0000 Subject: [PATCH] made transaction splitable better logging of transactions git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@596 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- qtbase/include/transaction.h | 5 ++ qtbase/include/transaction_p.h | 13 ++++- qtbase/src/transaction.cpp | 127 ++++++++++++++++++++++++++-------------- 3 files changed, 98 insertions(+), 47 deletions(-) diff --git a/qtbase/include/transaction.h b/qtbase/include/transaction.h index 8932010..576aed6 100644 --- a/qtbase/include/transaction.h +++ b/qtbase/include/transaction.h @@ -61,6 +61,9 @@ class WTransaction:public WHelper /**internal: execute a query on the web, used by subclasses*/ virtual QByteArray executeQuery(QString,QByteArray); + /**internal: execute a query on the web asynchronously*/ + virtual void startQuery(QString,QByteArray); + private slots: /**internal: triggers when the transaction times out*/ virtual void webTimeout(); @@ -68,6 +71,8 @@ class WTransaction:public WHelper virtual void webReady(); /**internal: triggers when the response errors out*/ virtual void webError(); + /**internal: collect query data*/ + virtual void endQuery(); signals: /**this signal is raised when the transaction finished executing*/ void webFinished(); diff --git a/qtbase/include/transaction_p.h b/qtbase/include/transaction_p.h index a2f8a51..e29414a 100644 --- a/qtbase/include/transaction_p.h +++ b/qtbase/include/transaction_p.h @@ -15,9 +15,13 @@ #include #include +#include #include "WTransaction" +class QTimer; +class QNetworkReply; + ///\internal private logger class class WTransaction::Log{ public: @@ -28,10 +32,12 @@ class WTransaction::Log{ void setError(const QString&); void setInfo(const QString&); private: - QByteArray req,rsp; + QString req,rsp; QString trn; WTransaction*parent; - int lvl; + int lvl,cnt; + + void outStr(const QString&); }; ///\internal private iface @@ -40,6 +46,9 @@ class WTransaction::Private { Stage m_stage; QString m_errtype,m_errstr,m_iface,m_wobstatus; Log*m_log; + QPointerm_rsp; + QByteArray m_rspdata; + QPointerm_qtimeout; }; #endif diff --git a/qtbase/src/transaction.cpp b/qtbase/src/transaction.cpp index 3e9ce5b..8e8f905 100644 --- a/qtbase/src/transaction.cpp +++ b/qtbase/src/transaction.cpp @@ -30,6 +30,7 @@ WTransaction::WTransaction(QString ifc) 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() @@ -40,6 +41,7 @@ WTransaction::WTransaction(const WTransaction&t) 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() @@ -86,12 +88,9 @@ static QList rqpairs(const QNetworkRequest&req) 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){ @@ -100,7 +99,7 @@ QByteArray WTransaction::executeQuery(QString hreq,QByteArray data) d->m_stage=Error; d->m_errtype="_iface"; d->m_errstr=tr("interface not found"); - return QByteArray(); + return; } //set target QUrl url=iface->url(); @@ -125,55 +124,65 @@ QByteArray WTransaction::executeQuery(QString hreq,QByteArray data) 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; @@ -181,13 +190,33 @@ QByteArray WTransaction::executeQuery(QString hreq,QByteArray data) 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(); @@ -222,16 +251,19 @@ QString WTransaction::errorType()const{return d->m_errtype;} 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() @@ -239,14 +271,20 @@ 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=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) @@ -277,13 +314,13 @@ void WTransaction::Log::setError(const QString&s) if(lvl0){ - 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 -- 1.7.2.5