From: konrad Date: Sat, 2 Oct 2010 18:16:31 +0000 (+0000) Subject: move transaction code into private class X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=ae574abb5cd9638332b6be1f9134f81e7616475d;p=web%2Fkonrad%2Fpack.git move transaction code into private class git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@597 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/qtbase/include/interface.h b/qtbase/include/interface.h index 70531fe..b89e9ee 100644 --- a/qtbase/include/interface.h +++ b/qtbase/include/interface.h @@ -30,6 +30,7 @@ class WInterface:public QObject WInterface(QString name); friend class WTransaction; + friend class WTransaction_Private; ///called by WTransaction to post a request QNetworkReply* post(const QNetworkRequest&request,const QByteArray&data); diff --git a/qtbase/include/transaction.h b/qtbase/include/transaction.h index 576aed6..103e277 100644 --- a/qtbase/include/transaction.h +++ b/qtbase/include/transaction.h @@ -20,6 +20,8 @@ #include "nullable.h" #include "WHelper" +class WTransaction_Private; + /**base class of all transactions*/ class WTransaction:public WHelper { @@ -31,7 +33,6 @@ class WTransaction:public WHelper Request,///m_rsp; QByteArray m_rspdata; QPointerm_qtimeout; + + public slots: + ///attach this private object to a master + WTransaction_Private* attach(WTransaction*); + ///detach this object from a master, delete it if there are no more masters + void detach(QObject*); + private: + ///internal reference counter + int m_refctr; }; #endif diff --git a/qtbase/src/transaction.cpp b/qtbase/src/transaction.cpp index 8e8f905..56fc80a 100644 --- a/qtbase/src/transaction.cpp +++ b/qtbase/src/transaction.cpp @@ -26,36 +26,27 @@ WTransaction::WTransaction(QString ifc) { - d=new Private; + d=new WTransaction_Private(this); 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=new Private; - d->m_stage=t.d->m_stage; - d->m_errstr=t.d->m_errstr; - d->m_errtype=t.d->m_errtype; - d->m_iface=t.d->m_iface; - d->m_log=0; + d=t.d->attach(this); connect(this,SIGNAL(webFinished()),this,SLOT(endQuery())); } WTransaction::~WTransaction() { - if(d)delete d; d=0; } WTransaction& WTransaction::operator=(const WTransaction&t) { - d->m_stage=t.d->m_stage; - d->m_errstr=t.d->m_errstr; - d->m_errtype=t.d->m_errtype; - d->m_iface=t.d->m_iface; + d->detach(this); + d=t.d->attach(this); return *this; } @@ -88,17 +79,18 @@ static QList rqpairs(const QNetworkRequest&req) return ret; } -void WTransaction::startQuery(QString hreq,QByteArray data) +void WTransaction::startQuery(QString hreq,QByteArray data){d->startQuery(hreq,data);} +void WTransaction_Private::startQuery(QString hreq,QByteArray data) { QNetworkRequest req; //find interface - WInterface *iface=WInterface::instance(d->m_iface); + WInterface *iface=WInterface::instance(m_iface); if(!iface){ - if(d->m_log)d->m_log->setError("cannot find interface."); + if(m_log)m_log->setError("cannot find interface."); else qDebug("Error: transaction cannot find interface."); - d->m_stage=Error; - d->m_errtype="_iface"; - d->m_errstr=tr("interface not found"); + m_stage=WTransaction::Error; + m_errtype="_iface"; + m_errstr=tr("interface not found"); return; } //set target @@ -108,7 +100,7 @@ void WTransaction::startQuery(QString hreq,QByteArray data) if(url.scheme().toLower()=="http")port=80; else port=443; } - if(d->m_log)d->m_log->setInfo(QString("New HTTP Request %1 URL %2\n\tto host=%3 port=%4 scheme=%5") + if(m_log)m_log->setInfo(QString("New HTTP Request %1 URL %2\n\tto host=%3 port=%4 scheme=%5") .arg(hreq) .arg(url.toString()) .arg(url.host()) @@ -124,79 +116,85 @@ void WTransaction::startQuery(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) - d->m_rsp=iface->post(req,data); + m_rsp=iface->post(req,data); //latest point of deletion: end of this transaction - d->m_rsp->setParent(this); + m_rsp->setParent(this); //log request - if(d->m_log){ - d->m_log->setRequ(hd2str(rqpairs(req)),esc(data)); + if(m_log){ + m_log->setRequ(hd2str(rqpairs(req)),esc(data)); } //we are requesting now... - d->m_stage=Request; + m_stage=WTransaction::Request; //schedule receiving - if(d->m_qtimeout.isNull()){ - d->m_qtimeout=new QTimer(this); - connect(d->m_qtimeout,SIGNAL(timeout()),this,SLOT(webTimeout())); + if(m_qtimeout.isNull()){ + m_qtimeout=new QTimer(this); + connect(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())); + m_qtimeout->setSingleShot(true); + m_qtimeout->start(iface->webTimeout()*1000); + connect(m_rsp,SIGNAL(finished()),this,SLOT(webReady())); + connect(m_rsp,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(webError())); } -void WTransaction::endQuery() +void WTransaction::endQuery(){d->endQuery();} +void WTransaction_Private::endQuery() { //sanity check - if(d->m_rsp.isNull())return; - d->m_rspdata=QByteArray(); + if(m_rsp.isNull())return; + m_rspdata=QByteArray(); //unschedule timeout - if(!d->m_qtimeout.isNull()) - d->m_qtimeout->stop(); + if(!m_qtimeout.isNull()) + m_qtimeout->stop(); //delete response object when done here QObject rspown; - connect(&rspown,SIGNAL(destroyed(QObject*)),d->m_rsp,SLOT(deleteLater())); + connect(&rspown,SIGNAL(destroyed(QObject*)),m_rsp,SLOT(deleteLater())); //process result - if(d->m_stage==Error && d->m_errtype=="_timeout"){ + if(m_stage==WTransaction::Error && m_errtype=="_timeout"){ //it did not finish yet, caught a timeout. - d->m_rsp->abort(); - d->m_errstr=tr("Web Request timed out."); - if(d->m_log)d->m_log->setError("Request timed out."); + m_rsp->abort(); + m_errstr=tr("Web Request timed out."); + if(m_log)m_log->setError("Request timed out."); return; }else //finished with low-level error? - if(d->m_stage==Error){ - 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)); + if(m_stage==WTransaction::Error){ + m_errstr="HTTP Error: "+m_rsp->errorString(); + if(m_log)m_log->setError(QString("Request finished with HTTP level error: %1").arg(m_errstr)); return; } //get data - d->m_wobstatus=d->m_rsp->rawHeader("X-WobResponse-Status"); - d->m_wobstatus=d->m_wobstatus.replace("\"","").trimmed().toLower(); - d->m_rspdata=d->m_rsp->readAll(); - if(d->m_log)d->m_log->setResp(hd2str(d->m_rsp->rawHeaderPairs()),esc(d->m_rspdata)); + m_wobstatus=m_rsp->rawHeader("X-WobResponse-Status"); + m_wobstatus=m_wobstatus.replace("\"","").trimmed().toLower(); + m_rspdata=m_rsp->readAll(); + if(m_log)m_log->setResp(hd2str(m_rsp->rawHeaderPairs()),esc(m_rspdata)); //check for high level error - int statcode=d->m_rsp->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + int statcode=m_rsp->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if(statcode!=200){ - 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)); + m_errstr=tr("HTTP Error, return code %1 %2") .arg(statcode).arg(m_rsp->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); + m_errtype="_HTTP"; + m_stage=WTransaction::Error; + if(m_log)m_log->setError(QString("Request finished with HTTP level error: %1").arg(m_errstr)); return; } - if(d->m_stage==Request){ - d->m_stage=Error; - d->m_errtype="_internal"; - d->m_errstr="Ooops: still in Request phase at end of response handling."; + if(m_stage==WTransaction::Request){ + m_stage=WTransaction::Error; + m_errtype="_internal"; + m_errstr="Ooops: still in Request phase at end of response handling."; } //remaining high level errors are handled by the generated code } -QByteArray WTransaction::executeQuery(QString hreq,QByteArray data) +QByteArray WTransaction::executeQuery(QString hreq,QByteArray data){return d->executeQuery(hreq,data);} +QByteArray WTransaction_Private::executeQuery(QString hreq,QByteArray data) { + //sanity check + if(!m_rsp.isNull() || m_stage==WTransaction::Request) + return QByteArray(); + //set up request startQuery(hreq,data); - if(d->m_rsp.isNull() || d->m_stage!=Request) + if(m_rsp.isNull() || m_stage!=WTransaction::Request) return QByteArray(); ///////////////////////////////////////////////////////////////////// @@ -206,37 +204,37 @@ QByteArray WTransaction::executeQuery(QString hreq,QByteArray data) loop.exec(); ///////////////////////////////////////////////////////////////////// - if(d->m_stage==Success) - return d->m_rspdata; + if(m_stage==WTransaction::Success) + return m_rspdata; else return QByteArray(); } -void WTransaction::webTimeout() +void WTransaction_Private::webTimeout() { - if(d->m_stage!=Request)return; + if(m_stage!=WTransaction::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"; + if(m_log)m_log->setInfo(QString("timeout in request")); + m_stage=WTransaction::Error; + m_errtype="_timeout"; emit webFinished(); } -void WTransaction::webReady() +void WTransaction_Private::webReady() { - if(d->m_stage!=Request)return; - if(d->m_log)d->m_log->setInfo(QString("finished request")); - d->m_stage=Success; - d->m_errtype=""; + if(m_stage!=WTransaction::Request)return; + if(m_log)m_log->setInfo(QString("finished request")); + m_stage=WTransaction::Success; + m_errtype=""; emit webFinished(); } -void WTransaction::webError() +void WTransaction_Private::webError() { - if(d->m_stage!=Request)return; - if(d->m_log)d->m_log->setInfo(QString("error in request")); - d->m_stage=Error; - d->m_errtype="_web"; + if(m_stage!=WTransaction::Request)return; + if(m_log)m_log->setInfo(QString("error in request")); + m_stage=WTransaction::Error; + m_errtype="_web"; emit webFinished(); } @@ -251,24 +249,33 @@ 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) +WTransaction::Log::Log(WTransaction*p,const QString&s,const QString&i) { + Q_ASSERT_X(p!=0,"WTransaction::Log constructor","Logger Parent must be a valid transaction object."); parent=p; + if(parent->d->m_log!=0)delete parent->d->m_log; parent->d->m_log=this; trn=s; + if(i.isNull()) + ifc=p->interface(); + else + ifc=i; cnt=logid++; WInterface*in=WInterface::instance(p->d->m_iface); if(in)lvl=in->logLevel(); else lvl=WInterface::LogOnError; if(lvl>WInterface::LogNone) - outStr(QString("Running transaction %1").arg(s)); + outStr(QString("Running transaction %1 on interface %2").arg(s).arg(ifc)); } WTransaction::Log::~Log() { - parent->d->m_log=0; + if(parent->d->m_log==this) + parent->d->m_log=0; } void WTransaction::Log::outStr(const QString&s) @@ -323,4 +330,33 @@ void WTransaction::Log::setError(const QString&s) } //show actual error outStr(QString("Transaction %1 Error: %2").arg(trn).arg(s)); -} \ No newline at end of file +} + +/*****************************************************************************/ + +WTransaction_Private::WTransaction_Private(WTransaction*trn) +{ + m_stage=WTransaction::Uninitialized; + m_log=0; + m_refctr=0; + attach(trn); + connect(this,SIGNAL(webFinished()),this,SLOT(endQuery())); +} + +WTransaction_Private* WTransaction_Private::attach(WTransaction*trn) +{ + m_refctr++; + connect(trn,SIGNAL(destroyed(QObject*)),this,SLOT(detach(QObject*))); + return this; +} + +void WTransaction_Private::detach(QObject*trn) +{ + m_refctr--; + if(m_refctr==0) + deleteLater(); + else if(trn){ + disconnect(trn); + trn->disconnect(this); + } +} diff --git a/qtbase/wbase.pro b/qtbase/wbase.pro index c8c9ac3..5903c99 100644 --- a/qtbase/wbase.pro +++ b/qtbase/wbase.pro @@ -14,6 +14,7 @@ HEADERS += \ include/helper.h \ include/object.h \ include/transaction.h \ + include/transaction_p.h \ include/interface.h SOURCES += \