[rkward-cvs] SF.net SVN: rkward:[3191] branches/2010_10_18_backend_restructuring_branch/ rkward/rbackend
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Wed Nov 17 13:29:41 UTC 2010
Revision: 3191
http://rkward.svn.sourceforge.net/rkward/?rev=3191&view=rev
Author: tfry
Date: 2010-11-17 13:29:41 +0000 (Wed, 17 Nov 2010)
Log Message:
-----------
Almost compilable, now
Modified Paths:
--------------
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp
Added Paths:
-----------
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.h
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt 2010-11-17 13:00:50 UTC (rev 3190)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt 2010-11-17 13:29:41 UTC (rev 3191)
@@ -34,12 +34,13 @@
rkrbackendprotocol_frontend.cpp
)
-#SET(RBACKEND_SPLIT 1)
+SET(RBACKEND_SPLIT 1)
IF(RBACKEND_SPLIT)
SET (
rbackend_STAT_SRCS
${rbackend_frontend_SRCS}
${rbackend_shared_SRCS}
+ rkfrontendtransmitter.cpp
)
QT4_AUTOMOC(${rbackend_STAT_SRCS})
ADD_LIBRARY(rbackend STATIC ${rbackend_STAT_SRCS})
@@ -48,7 +49,7 @@
QT4_AUTOMOC(${rbackend_backend_SRCS})
ADD_DEFINITIONS (-DRKWARD_SPLIT_PROCESS)
KDE4_ADD_EXECUTABLE(rkward.rbackend ${rbackend_backend_SRCS} ${rbackend_shared_SRCS})
- TARGET_LINK_LIBRARIES(rkward.rbackend ${R_USED_LIBS} ${CMAKE_THREAD_LIBS_INIT})
+ TARGET_LINK_LIBRARIES(rkward.rbackend ${R_USED_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${KDE4_KDECORE_LIBS})
LINK_DIRECTORIES(${R_SHAREDLIBDIR})
ELSE(RBACKEND_SPLIT)
SET (
Added: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.cpp (rev 0)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.cpp 2010-11-17 13:29:41 UTC (rev 3191)
@@ -0,0 +1,155 @@
+/***************************************************************************
+ rkfrontendtransmitter - description
+ -------------------
+ begin : Thu Nov 04 2010
+ copyright : (C) 2010 by Thomas Friedrichsmeier
+ email : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "rkfrontendtransmitter.h"
+
+#include "rkrbackendprotocol_frontend.h"
+
+#include "kstandarddirs.h"
+#include <QCoreApplication>
+
+#include "../debug.h"
+
+RKFrontendTransmitter* RKFrontendTransmitter::_instance = 0;
+RKFrontendTransmitter::RKFrontendTransmitter () : QThread () {
+ RK_TRACE (RBACKEND);
+
+ // start server
+ connection = 0;
+ if (!server.listen ("rkward")) handleTransmitError ("failure to start frontend server: " + server.errorString ());
+ connect (&server, SIGNAL (newConnection ()), this, SLOT (connectAndEnterLoop ()));
+
+ // start backend
+ QStringList args;
+ args.append ("--debug-level " + QString::number (RK_Debug_Level));
+ args.append ("--server-name " + server.fullServerName ());
+ backend.setProcessChannelMode (QProcess::MergedChannels); // at least for now. Seems difficult to get interleaving right, without this.
+ connect (&backend, SIGNAL (readyReadStandardOutput ()), this, SLOT (newProcessOutput ()));
+ connect (&backend, SIGNAL (finished (int, QProcess::ExitStatus)), this, SLOT (backendExit (int, QProcess::ExitStatus)));
+ backend.start (KStandardDirs::findExe ("rkward.rbackend", QCoreApplication::applicationDirPath ()), args, QIODevice::ReadOnly);
+
+ RK_ASSERT (_instance == 0);
+ _instance = this;
+}
+
+RKFrontendTransmitter::~RKFrontendTransmitter () {
+ RK_TRACE (RBACKEND);
+
+ RK_ASSERT (!server.isListening ());
+ delete connection;
+}
+
+void RKFrontendTransmitter::run () {
+ RK_ASSERT (connection);
+
+ connection->moveToThread (this);
+ connect (connection, SIGNAL (stateChanged (QLocalSocket::LocalSocketState)), this, SLOT (connectionStateChanged (QLocalSocket::LocalSocketState)));
+ connect (connection, SIGNAL (readyRead ()), this, SLOT (newConnectionData ()));
+ backend.moveToThread (this);
+
+ exec ();
+}
+
+void RKFrontendTransmitter::connectAndEnterLoop () {
+ RK_TRACE (RBACKEND);
+ RK_ASSERT (server.hasPendingConnections ());
+
+ connection = server.nextPendingConnection ();
+ server.close ();
+
+ start ();
+}
+
+void RKFrontendTransmitter::newProcessOutput () {
+ RK_TRACE (RBACKEND);
+#warning TODO: fix interleaving
+ QString output = QString::fromLocal8Bit (backend.readAll ());
+ handleOutput (output, output.size (), ROutput::Warning);
+}
+
+void RKFrontendTransmitter::newConnectionData () {
+ RK_TRACE (RBACKEND);
+
+ if (!connection->canReadLine ()) return;
+
+ QString line = QString::fromLocal8Bit (connection->readLine ());
+ bool ok;
+ int expected_length = line.toInt (&ok);
+ if (!ok) handleTransmitError ("Protocol header error. Last connection error was: " + connection->errorString ());
+
+ QByteArray receive_buffer;
+ while (receive_buffer.length () < expected_length) {
+ if (connection->bytesAvailable ()) {
+ receive_buffer.append (connection->read (expected_length - receive_buffer.length ()));
+ } else {
+ connection->waitForReadyRead (1000);
+ if (!connection->isOpen ()) {
+ handleTransmitError ("Connection closed unexepctedly. Last error: " + connection->errorString ());
+ return;
+ }
+ }
+ }
+
+ RBackendRequest *req = RKRBackendSerializer::unserialize (receive_buffer);
+ RKRBackendEvent* event = new RKRBackendEvent (req);
+ qApp->postEvent (RKRBackendProtocolFrontend::instance ()->parent (), event);
+}
+
+void RKFrontendTransmitter::backendExit (int exitcode, QProcess::ExitStatus exitstatus) {
+ RK_TRACE (RBACKEND);
+
+ RBackendRequest* req = new RBackendRequest (false, RBackendRequest::BackendExit);
+ RKRBackendEvent* event = new RKRBackendEvent (req);
+ qApp->postEvent (RKRBackendProtocolFrontend::instance ()->parent (), event);
+}
+
+void RKFrontendTransmitter::connectionStateChanged (QLocalSocket::LocalSocketState state) {
+ if (state != QLocalSocket::UnconnectedState) return; // only interested in connection failure
+ RK_TRACE (RBACKEND);
+
+ RBackendRequest* req = new RBackendRequest (false, RBackendRequest::BackendExit);
+ RKRBackendEvent* event = new RKRBackendEvent (req);
+ qApp->postEvent (RKRBackendProtocolFrontend::instance ()->parent (), event);
+}
+
+void RKFrontendTransmitter::writeRequest (RBackendRequest *request) {
+ RK_TRACE (RBACKEND);
+
+ QByteArray buffer = RKRBackendSerializer::serialize (*request);
+ connection->write (QString::number (buffer.length ()).toLocal8Bit () + "\n");
+ connection->write (buffer);
+ delete request;
+}
+
+void RKFrontendTransmitter::customEvent (QEvent *e) {
+ if (((int) e->type ()) == ((int) RKRBackendEvent::RKWardEvent)) {
+ RKRBackendEvent *ev = static_cast<RKRBackendEvent*> (e);
+ writeRequest (ev->data ());
+ } else {
+ RK_ASSERT (false);
+ return;
+ }
+}
+
+void RKFrontendTransmitter::handleTransmitError (const QString &message) {
+ RK_TRACE (RBACKEND);
+ #warning: Show those errors to the user!
+
+ qDebug ("%s", qPrintable (message));
+}
+
+#include "rkfrontendtransmitter.moc"
Added: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.h (rev 0)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkfrontendtransmitter.h 2010-11-17 13:29:41 UTC (rev 3191)
@@ -0,0 +1,65 @@
+/***************************************************************************
+ rkfrontendtransmitter - description
+ -------------------
+ begin : Thu Nov 04 2010
+ copyright : (C) 2010 by Thomas Friedrichsmeier
+ email : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef RKFRONTENDTRANSMITTER_H
+#define RKFRONTENDTRANSMITTER_H
+
+#include "rkrbackendprotocol_shared.h"
+
+#ifdef RKWARD_THREADED
+# error This file should only be compiled for split process backends!
+#endif
+
+#include <QLocalServer>
+#include <QLocalSocket>
+#include <QProcess>
+#include <QThread>
+
+class RKFrontendTransmitter : public QThread, public RKROutputBuffer {
+Q_OBJECT
+public:
+ RKFrontendTransmitter ();
+ ~RKFrontendTransmitter ();
+
+ static RKFrontendTransmitter* instance () { return _instance; };
+
+ void run ();
+
+ bool doMSleep (int delay) {
+ msleep (delay);
+ return true;
+ };
+ void writeRequest (RBackendRequest *request);
+ void customEvent (QEvent *e);
+private slots:
+ void connectAndEnterLoop ();
+ void newProcessOutput ();
+ void newConnectionData ();
+ void backendExit (int exitcode, QProcess::ExitStatus exitstatus);
+ void connectionStateChanged (QLocalSocket::LocalSocketState state);
+private:
+ void handleTransmitError (const QString &message);
+
+ int current_request_length;
+ QProcess backend;
+ QLocalServer server;
+ QLocalSocket* connection;
+ static RKFrontendTransmitter *_instance;
+};
+
+#endif
+
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp 2010-11-17 13:00:50 UTC (rev 3190)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp 2010-11-17 13:29:41 UTC (rev 3191)
@@ -33,6 +33,8 @@
#else
# include <QLocalSocket>
# include <QMutex>
+# include "kcomponentdata.h"
+# include "kglobal.h"
#endif
#ifdef RKWARD_THREADED
@@ -84,8 +86,9 @@
public:
RKRBackendTransmitter (const QString &servername) {
RK_TRACE (RBACKEND);
+ RK_ASSERT (_instance == 0);
+ _instance = this;
- current_request = 0;
connection.connectToServer (servername); // acutal connection will be done inside run()
};
@@ -120,11 +123,12 @@
};
void postRequest (RBackendRequest *request) {
- QMutextLocker (request_mutex);
-
RK_TRACE (RBACKEND);
RK_ASSERT (request);
+
+ request_mutex.lock ();
current_requests.append (request);
+ request_mutex.unlock ();
}
void handleRequestInternal (RBackendRequest *request) {
@@ -133,7 +137,7 @@
// send request
QByteArray buffer = RKRBackendSerializer::serialize (*request);
- connection.write (QString::number (buffer.length ()).local8Bit ().data () + "\n");
+ connection.write (QString::number (buffer.length ()).toLocal8Bit () + "\n");
connection.write (buffer);
while (connection.bytesToWrite ()) {
if (!connection.waitForBytesWritten ()) handleTransmitError ("Could not connect: %s");
@@ -148,31 +152,7 @@
// wait for reply
// NOTE: currently, in the backend, we *never* expect a read without a synchronous request
- QByteArray receive_buffer;
- unsigned int expected_length = 0;
- bool got_header = false;
- while (1) {
- bool have_data = waitForReadyRead ();
- if (!connection.isOpen ()) {
- handleTransmitError ("Connection closed unexepctedly. Last error: %s");
- return;
- }
- if (!have_data) continue;
- if (!got_header) {
- if (!connection.canReadLine ()) continue;
-
- QString line = QString::fromLocal8Bit (connection.readLine ());
- bool ok;
- expected_length = line.toInt (&ok);
- if (!ok) handleTransmitError ("Protocol header error. Last connection error was: %s");
- got_header = true;
- }
-
- receive_buffer.append (connection.readAll (expected_length - receive_buffer.length ()));
- if (receive_buffer.length () >= expected_length () break;
- }
-
- RBackendRequest* reply = RBackendRequest::unserialize (fetchTransmission (true));
+ RBackendRequest* reply = RKRBackendSerializer::unserialize (fetchTransmission (true));
request->mergeReply (reply);
RK_ASSERT (reply->done);
delete reply;
@@ -185,11 +165,11 @@
@note @em If a transmission is available, this will always block until the transmission has been received in full. */
QByteArray fetchTransmission (bool block) {
QByteArray receive_buffer;
- unsigned int expected_length = 0;
+ int expected_length = 0;
bool got_header = false;
- boo have_data = false;
+ bool have_data = false;
while (1) {
- bool have_data = have_data || waitForReadyRead (1);
+ have_data = have_data || connection.waitForReadyRead (1);
if (!connection.isOpen ()) {
handleTransmitError ("Connection closed unexepctedly. Last error: %s");
return receive_buffer;
@@ -209,13 +189,13 @@
got_header = true;
}
- receive_buffer.append (connection.readAll (expected_length - receive_buffer.length ()));
+ receive_buffer.append (connection.read (expected_length - receive_buffer.length ()));
if (receive_buffer.length () >= expected_length) return receive_buffer;
}
}
void flushOutput (bool force) {
- ROutputList out = RKRBackend::flushOutput (force);
+ ROutputList out = RKRBackend::this_pointer->flushOutput (force);
if (out.isEmpty ()) return;
// output request would not strictly need to be synchronous. However, making them synchronous ensures that the frontend is keeping up with the output sent by the backend.
@@ -231,13 +211,16 @@
QLocalSocket connection;
QList<RBackendRequest *> current_requests; // there *can* be multiple active requests (if the first ones are asynchronous)
QMutex request_mutex;
+ static RKRBackendTransmitter* _instance;
+ static RKRBackendTransmitter* instance () { return _instance; };
};
+ RKRBackendTransmitter* RKRBackendTransmitter::_instance = 0;
int RK_Debug_Level = 2;
int RK_Debug_Flags = ALL;
QMutex RK_Debug_Mutex;
- void RKDebugMessageOutput (QtMsgType type, const char *msg) {
+/* void RKDebugMessageOutput (QtMsgType type, const char *msg) {
RK_Debug_Mutex.lock ();
if (type == QtFatalMsg) {
fprintf (stderr, "%s\n", msg);
@@ -246,7 +229,7 @@
RKSettingsModuleDebug::debug_file->write ("\n");
RKSettingsModuleDebug::debug_file->flush ();
RK_Debug_Mutex.unlock ();
- }
+ } */
int main(int argc, char *argv[]) {
QCoreApplication app (argc, argv);
@@ -254,7 +237,7 @@
KGlobal::locale (); // to initialize it in the primary thread
QString servername;
- QStringList args = app->arguments ();
+ QStringList args = app.arguments ();
for (int i = 1; i < args.count (); ++i) {
if (args[i].startsWith ("--debug-level")) {
RK_Debug_Level = args.value (++i, QString ()).toInt ();
@@ -264,7 +247,7 @@
printf ("unkown argument %s", qPrintable (args[i]));
}
}
- if (severname.isEmpty ()) {
+ if (servername.isEmpty ()) {
printf ("no server to connect to");
}
@@ -273,7 +256,6 @@
transmitter.start ();
RKRBackend::this_pointer->run ();
}
-#error
#endif
RKRBackendProtocolBackend* RKRBackendProtocolBackend::_instance = 0;
@@ -313,7 +295,7 @@
RKRBackendEvent* event = new RKRBackendEvent (request);
qApp->postEvent (RKRBackendProtocolFrontend::instance (), event);
#else
- RBackendTransmitter::instance ()->postRequest (request);
+ RKRBackendTransmitter::instance ()->postRequest (request);
#endif
}
@@ -325,7 +307,7 @@
#ifdef RKWARD_THREADED
RKRBackendThread::instance->publicmsleep (delay);
#else
- RKRBackendTransmitter::instance->publicmsleep (delay);
+ RKRBackendTransmitter::instance ()->publicmsleep (delay);
#endif
}
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp 2010-11-17 13:00:50 UTC (rev 3190)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp 2010-11-17 13:29:41 UTC (rev 3191)
@@ -25,161 +25,13 @@
# include "rkrbackend.h"
# include "rkrbackendprotocol_backend.h"
#else
-# include <QLocalServer>
-# include <QLocalSocket>
-# include <QProcess>
+# include "rkfrontendtransmitter.h"
# include <QCoreApplication>
#endif
#include "../debug.h"
#ifndef RKWARD_THREADED
- class RKFrontendTransmitter : public QThread, public RKROutputBuffer {
- Q_OBJECT
- public:
- RKFrontendTransmitter () {
- RK_TRACE (RBACKEND);
-
- // start server
- connection = 0;
- if (!server.listen ("rkward")) handleTransmitError ("failure to start frontend server: " + server.errorString ());
- connect (&server, SIGNAL (newConnection ()), this, SLOT (connectAndEnterLoop ()));
-
- // start backend
- QStringList args;
- args.append ("--debug-level " + QString::number (RK_Debug_Level));
- args.append ("--server-name " + server.fullServerName ());
- backend.setProcessChannelMode (QProcess::MergedChannels); // at least for now. Seems difficult to get interleaving right, without this.
- connect (&backend, SIGNAL (readyReadStandardOutput ()), this, SLOT (newProcessOutput ()));
- connect (&backend, SIGNAL (finished (int, QProcess::ExitStatus)), this, SLOT (backendExit (int, QProcess::ExitStatus)));
- backend.start ("rkward_backend", args, QIODevice::ReadOnly);
-
- RK_ASSERT (_instance == 0);
- _instance = this;
- };
-
- ~RKFrontendTransmitter () {
- RK_TRACE (RBACKEND);
-
- RK_ASSERT (!server.isListening ());
- delete connection;
- };
-
- static RKFrontendTransmitter* instance () { return _instance; };
-
- void run () {
- RK_ASSERT (connection);
-
- connection->moveToThread (this);
- connect (connection, SIGNAL (stateChanged (QLocalSocket::LocalSocketState)), this, SLOT (connectionStateChanged (QLocalSocket::LocalSocketState)));
- connect (connection, SIGNAL (readyRead ()), this, SLOT (newConnectionData ()));
- backend.moveToThread (this);
-
- exec ();
- };
-
- bool doMSleep (int delay) {
- msleep (delay);
- return true;
- };
- private slots:
- void connectAndEnterLoop () {
- RK_TRACE (RBACKEND);
- RK_ASSERT (server.hasPendingConnections ());
-
- connection = server.nextPendingConnection ();
- server.close ();
-
- start ();
- };
-
- void newProcessOutput () {
- RK_TRACE (RBACKEND);
-#warning TODO: fix interleaving
- QString output = QString::fromLocal8Bit (backend.readAll ());
- handleOutput (output, output.size (), ROutput::Warning);
- };
-
- void newConnectionData () {
- RK_TRACE (RBACKEND);
-
- if (!connection->canReadLine ()) return;
-
- QString line = QString::fromLocal8Bit (connection->readLine ());
- bool ok;
- int expected_length = line.toInt (&ok);
- if (!ok) handleTransmitError ("Protocol header error. Last connection error was: " + connection->errorString ());
-
- QByteArray receive_buffer;
- while (receive_buffer.length () < expected_length) {
- if (connection->bytesAvailable ()) {
- receive_buffer.append (connection->read (expected_length - receive_buffer.length ()));
- } else {
- connection->waitForReadyRead (1000);
- if (!connection->isOpen ()) {
- handleTransmitError ("Connection closed unexepctedly. Last error: " + connection->errorString ());
- return;
- }
- }
- }
-
- RBackendRequest *req = RKRBackendSerializer::unserialize (receive_buffer);
- RKRBackendEvent* event = new RKRBackendEvent (req);
- qApp->postEvent (RKRBackendProtocolFrontend::instance ()->parent (), event);
- };
-
- void backendExit (int exitcode, QProcess::ExitStatus exitstatus) {
- RK_TRACE (RBACKEND);
-
- RBackendRequest* req = new RBackendRequest (false, RBackendRequest::BackendExit);
- RKRBackendEvent* event = new RKRBackendEvent (req);
- qApp->postEvent (RKRBackendProtocolFrontend::instance ()->parent (), event);
- };
-
- void connectionStateChanged (QLocalSocket::LocalSocketState state) {
- if (state != QLocalSocket::UnconnectedState) return; // only interested in connection failure
- RK_TRACE (RBACKEND);
-
- RBackendRequest* req = new RBackendRequest (false, RBackendRequest::BackendExit);
- RKRBackendEvent* event = new RKRBackendEvent (req);
- qApp->postEvent (RKRBackendProtocolFrontend::instance ()->parent (), event);
- };
-
- void writeRequest (RBackendRequest *request) {
- RK_TRACE (RBACKEND);
-
- QByteArray buffer = RKRBackendSerializer::serialize (*request);
- connection->write (QString::number (buffer.length ()).toLocal8Bit () + "\n");
- connection->write (buffer);
- delete request;
- };
-
- void customEvent (QEvent *e) {
- if (((int) e->type ()) == ((int) RKRBackendEvent::RKWardEvent)) {
- RKRBackendEvent *ev = static_cast<RKRBackendEvent*> (e);
- writeRequest (ev->data ());
- } else {
- RK_ASSERT (false);
- return;
- }
- };
- private:
- void handleTransmitError (const QString &message) {
- RK_TRACE (RBACKEND);
- #warning: Show those errors to the user!
-
- qDebug ("%s", qPrintable (message));
- };
-
- int current_request_length;
- QProcess backend;
- QLocalServer server;
- QLocalSocket* connection;
- static RKFrontendTransmitter *_instance;
- };
- RKFrontendTransmitter* RKFrontendTransmitter::_instance = 0;
-
- #include "rkrbackendprotocol_frontend.moc"
#endif
RKRBackendProtocolFrontend* RKRBackendProtocolFrontend::_instance = 0;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the rkward-tracker
mailing list