made transaction splitable
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Thu, 30 Sep 2010 18:47:29 +0000 (18:47 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Thu, 30 Sep 2010 18:47:29 +0000 (18:47 +0000)
better logging of transactions

git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@596 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

qtbase/include/transaction.h
qtbase/include/transaction_p.h
qtbase/src/transaction.cpp

index 8932010..576aed6 100644 (file)
@@ -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();
index a2f8a51..e29414a 100644 (file)
 
 #include <QByteArray>
 #include <QString>
+#include <QPointer>
 
 #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;
+               QPointer<QNetworkReply>m_rsp;
+               QByteArray m_rspdata;
+               QPointer<QTimer>m_qtimeout;
 };
 
 #endif
index 3e9ce5b..8e8f905 100644 (file)
@@ -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<QNetworkReply::RawHeaderPair> 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<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;
@@ -255,11 +293,10 @@ void WTransaction::Log::setRequ(const QString&h,const QString&d)
 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;
@@ -268,7 +305,7 @@ void WTransaction::Log::setResp(const QString&h,const QString&d)
 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)
@@ -277,13 +314,13 @@ 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