summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Trueg <trueg@kde.org>2012-04-30 16:01:19 (GMT)
committerSebastian Trueg <trueg@kde.org>2012-04-30 16:01:19 (GMT)
commit437abbe0995a671c8b3ce6cd958f49ffad35a188 (patch)
tree118394efdc9329ddc0e8e183b7b410b98e0c0e3d
parentc33c33e62177dd74885d4507c767b98c9a4608d5 (diff)
parente8f19187eb0429d7d4a5242967dcd73d365353a9 (diff)
Merge branch 'feature/nonQObjectSockets'
-rw-r--r--ChangeLog5
-rw-r--r--client/CMakeLists.txt5
-rw-r--r--client/clientconnection.cpp140
-rw-r--r--client/clientconnection.h11
-rw-r--r--client/clientconnection_p.h9
-rw-r--r--client/clientmodel.cpp2
-rw-r--r--client/localsocketclient.cpp50
-rw-r--r--client/localsocketclient.h5
-rw-r--r--client/socket.cpp161
-rw-r--r--client/socket.h103
-rw-r--r--client/socketstream.cpp567
-rw-r--r--client/socketstream.h108
-rw-r--r--client/tcpclient.cpp4
13 files changed, 1075 insertions, 95 deletions
diff --git a/ChangeLog b/ChangeLog
index 59fc4d5..0a95b62 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,7 +8,10 @@
need arises we might call ID_TO_IRI() to convert them into URIs.
* New boolean option "noStatementSignals" in the Virtuoso backend which will disable
Model::statementsAdded() and friends.
-
+ * Improved local unix socket communication in the server/client system:
+ A custom socket implementation as a replacment for QLocalSocket makes it possible to
+ use one socket across threads.
+
2.7.6
* Support for the new SPARQL 1.1 DELETE statement which omits the graph to delete from
for faster removeAllStatement execution.
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 6547d27..c1fa916 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -14,8 +14,8 @@ include_directories(
)
set(soprano_client_SRC
- ${soprano_server_SOURCE_DIR}/datastream.cpp
- tcpclient.cpp
+ socket.cpp
+ socketstream.cpp
localsocketclient.cpp
clientconnection.h
clientconnection.cpp
@@ -89,7 +89,6 @@ INSTALL(TARGETS sopranoclient
install(
FILES
- tcpclient.h
localsocketclient.h
DESTINATION include/soprano
)
diff --git a/client/clientconnection.cpp b/client/clientconnection.cpp
index 8f6045a..2246c10 100644
--- a/client/clientconnection.cpp
+++ b/client/clientconnection.cpp
@@ -1,7 +1,7 @@
/*
* This file is part of Soprano Project.
*
- * Copyright (C) 2007-2010 Sebastian Trueg <trueg@kde.org>
+ * Copyright (C) 2007-2012 Sebastian Trueg <trueg@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,7 +22,8 @@
#include "clientconnection.h"
#include "clientconnection_p.h"
#include "commands.h"
-#include "datastream.h"
+#include "socketstream.h"
+#include "socket.h"
#include "node.h"
#include "statement.h"
@@ -30,7 +31,6 @@
#include "bindingset.h"
#include "backend.h"
-#include <QtCore/QIODevice>
#include <QtCore/QThread>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
@@ -45,7 +45,8 @@ namespace {
}
-Soprano::Client::SocketHandler::SocketHandler( ClientConnectionPrivate* client, QIODevice* socket )
+#ifdef Q_OS_WIN
+Soprano::Client::SocketHandler::SocketHandler( ClientConnectionPrivate* client, Socket* socket )
: QObject(),
m_client( client ),
m_socket( socket )
@@ -59,17 +60,21 @@ Soprano::Client::SocketHandler::~SocketHandler()
m_client->sockets.removeAll( m_socket );
delete m_socket;
}
-
+#endif
Soprano::Client::ClientConnection::ClientConnection( QObject* parent )
: QObject( parent ),
d( new ClientConnectionPrivate() )
{
+#ifndef Q_OS_WIN
+ d->socket = 0;
+#endif
}
Soprano::Client::ClientConnection::~ClientConnection()
{
+#ifdef Q_OS_WIN
d->socketMutex.lock();
// the sockets need to be deleted in their respective threads.
// this is what d->socketStorage does. We only close them here.
@@ -78,25 +83,29 @@ Soprano::Client::ClientConnection::~ClientConnection()
socket->close();
}
d->socketMutex.unlock();
+#else
+ delete d->socket;
+#endif
delete d;
}
-QIODevice* Soprano::Client::ClientConnection::socketForCurrentThread()
+Soprano::Socket *Soprano::Client::ClientConnection::getSocket()
{
- if ( isConnectedInCurrentThread() ) {
+#ifdef Q_OS_WIN
+ if ( isConnected() ) {
return d->socketStorage.localData()->socket();
}
- else if ( QIODevice* socket = newConnection() ) {
+ else if ( Socket* socket = newConnection() ) {
d->socketMutex.lock();
SocketHandler* cleaner = new SocketHandler( d, socket );
d->sockets.append( socket );
d->socketMutex.unlock();
d->socketStorage.setLocalData( cleaner );
- return socket;
}
-
- return 0;
+#else
+ return d->socket;
+#endif
}
@@ -104,10 +113,10 @@ int Soprano::Client::ClientConnection::createModel( const QString& name, const Q
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::createModel)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return 0;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_CREATE_MODEL );
stream.writeString( name );
@@ -136,10 +145,10 @@ void Soprano::Client::ClientConnection::removeModel( const QString& name )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::removeModel)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_REMOVE_MODEL );
stream.writeString( name );
@@ -164,10 +173,10 @@ Soprano::BackendFeatures Soprano::Client::ClientConnection::supportedFeatures()
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::supportedFeatures)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return BackendFeatureNone;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_SUPPORTED_FEATURES );
@@ -194,10 +203,10 @@ Soprano::Error::ErrorCode Soprano::Client::ClientConnection::addStatement( int m
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::addStatement)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Error::convertErrorCode( lastError().code() );
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_ADD_STATEMENT );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -225,10 +234,10 @@ int Soprano::Client::ClientConnection::listContexts( int modelId )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::listContexts)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return 0;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_LIST_CONTEXTS );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -255,10 +264,10 @@ int Soprano::Client::ClientConnection::executeQuery( int modelId, const QString
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::executeQuery)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return 0;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_QUERY );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -288,10 +297,10 @@ int Soprano::Client::ClientConnection::listStatements( int modelId, const Statem
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::listStatements)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return 0;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_LIST_STATEMENTS );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -319,10 +328,10 @@ Soprano::Error::ErrorCode Soprano::Client::ClientConnection::removeAllStatements
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::removeAllStatements)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Error::convertErrorCode( lastError().code() );
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_REMOVE_ALL_STATEMENTS );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -350,10 +359,10 @@ Soprano::Error::ErrorCode Soprano::Client::ClientConnection::removeStatement( in
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::removeStatement)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Error::convertErrorCode( lastError().code() );
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_REMOVE_STATEMENT );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -381,10 +390,10 @@ int Soprano::Client::ClientConnection::statementCount( int modelId )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::statementCount)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return -1;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_STATEMENT_COUNT );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -411,10 +420,10 @@ bool Soprano::Client::ClientConnection::containsStatement( int modelId, const St
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::containsStatement)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return false;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_CONTAINS_STATEMENT );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -442,10 +451,10 @@ bool Soprano::Client::ClientConnection::containsAnyStatement( int modelId, const
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::containsAnyStatement)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return false;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_CONTAINS_ANY_STATEMENT );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -473,10 +482,10 @@ bool Soprano::Client::ClientConnection::isEmpty( int modelId )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::isEmpty)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return false;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_IS_EMPTY );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -503,10 +512,10 @@ Soprano::Node Soprano::Client::ClientConnection::createBlankNode( int modelId )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::createBlankNode)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Node();
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_MODEL_CREATE_BLANK_NODE );
stream.writeUnsignedInt32( ( quint32 )modelId );
@@ -533,10 +542,10 @@ bool Soprano::Client::ClientConnection::iteratorNext( int id )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::iteratorNext)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return false;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_NEXT );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -563,10 +572,10 @@ Soprano::Node Soprano::Client::ClientConnection::nodeIteratorCurrent( int id )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::nodeIteratorCurrent)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Node();
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_CURRENT_NODE );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -593,10 +602,10 @@ Soprano::Statement Soprano::Client::ClientConnection::statementIteratorCurrent(
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::statementIteratorCurrent)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Statement();
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_CURRENT_STATEMENT );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -623,10 +632,10 @@ Soprano::BindingSet Soprano::Client::ClientConnection::queryIteratorCurrent( int
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::queryIteratorCurrent)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return BindingSet();
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_CURRENT_BINDINGSET );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -653,10 +662,10 @@ Soprano::Statement Soprano::Client::ClientConnection::queryIteratorCurrentStatem
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::queryIteratorCurrentStatement)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return Statement();
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_CURRENT_STATEMENT );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -682,10 +691,10 @@ int Soprano::Client::ClientConnection::queryIteratorType( int id )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::queryIteratorType)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return 0;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_QUERY_TYPE );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -712,10 +721,10 @@ bool Soprano::Client::ClientConnection::queryIteratorBoolValue( int id )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::queryIteratorBoolValue)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return false;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_QUERY_BOOL_VALUE );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -741,10 +750,10 @@ void Soprano::Client::ClientConnection::iteratorClose( int id )
{
//qDebug() << this << QTime::currentTime().toString( "hh:mm:ss.zzz" ) << QThread::currentThreadId() << "(ClientConnection::iteratorClose)";
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_ITERATOR_CLOSE );
stream.writeUnsignedInt32( ( quint32 )id );
@@ -766,10 +775,10 @@ void Soprano::Client::ClientConnection::iteratorClose( int id )
bool Soprano::Client::ClientConnection::checkProtocolVersion()
{
- QIODevice* socket = socketForCurrentThread();
+ Socket* socket = getSocket();
if ( !socket )
return false;
- DataStream stream( socket );
+ SocketStream stream( socket );
stream.writeUnsignedInt16( COMMAND_SUPPORTS_PROTOCOL_VERSION );
stream.writeUnsignedInt32( ( quint32 )PROTOCOL_VERSION );
@@ -795,17 +804,28 @@ bool Soprano::Client::ClientConnection::checkProtocolVersion()
}
-bool Soprano::Client::ClientConnection::connectInCurrentThread()
+bool Soprano::Client::ClientConnection::connect()
{
- return( socketForCurrentThread() != 0 );
+#ifndef Q_OS_WIN
+ if(!d->socket) {
+ d->socket = newConnection();
+ }
+#endif
+ return( getSocket() != 0 );
}
-bool Soprano::Client::ClientConnection::isConnectedInCurrentThread()
+bool Soprano::Client::ClientConnection::isConnected()
{
+#ifdef Q_OS_WIN
return ( d->socketStorage.hasLocalData() &&
isConnected( d->socketStorage.localData()->socket() ) );
+#else
+ return( d->socket != 0 && d->socket.isConnected() );
+#endif
}
#include "clientconnection.moc"
+#ifdef Q_OS_WIN
#include "clientconnection_p.moc"
+#endif
diff --git a/client/clientconnection.h b/client/clientconnection.h
index 72b14f9..bfb3d4d 100644
--- a/client/clientconnection.h
+++ b/client/clientconnection.h
@@ -24,6 +24,7 @@
#include "error.h"
#include "sopranotypes.h"
+#include "socket.h"
#include <QtCore/QObject>
#include <QtCore/QList>
@@ -87,19 +88,19 @@ namespace Soprano {
/// trueg: this is an awful design which simply grew over time.
/// At some point this needs fixing a lot. Maybe by simply not
/// Using Qt for communication.
- bool connectInCurrentThread();
- bool isConnectedInCurrentThread();
+ bool connect();
+ bool isConnected();
protected:
/**
* Creates a new IODevice for communication.
* ClientConnection will create one for each thread.
*/
- virtual QIODevice* newConnection() = 0;
- virtual bool isConnected( QIODevice* dev ) = 0;
+ virtual Socket* newConnection() = 0;
+ virtual bool isConnected( Socket* ) { return false; }
private:
- QIODevice* socketForCurrentThread();
+ Socket* getSocket();
ClientConnectionPrivate* const d;
};
diff --git a/client/clientconnection_p.h b/client/clientconnection_p.h
index ee176a8..003472f 100644
--- a/client/clientconnection_p.h
+++ b/client/clientconnection_p.h
@@ -1,7 +1,7 @@
/*
* This file is part of Soprano Project.
*
- * Copyright (C) 2007-2009 Sebastian Trueg <trueg@kde.org>
+ * Copyright (C) 2007-2012 Sebastian Trueg <trueg@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -26,11 +26,13 @@
#include <QtCore/QList>
#include <QtCore/QThreadStorage>
#include <QtCore/QIODevice>
+#include "socket.h"
class QThread;
namespace Soprano {
namespace Client {
+#ifdef Q_OS_WIN
class ClientConnectionPrivate;
/**
@@ -53,13 +55,18 @@ namespace Soprano {
ClientConnectionPrivate* m_client;
QIODevice* m_socket;
};
+#endif
class ClientConnectionPrivate
{
public:
+#ifndef Q_OS_WIN
+ Socket* socket;
+#else
QList<QIODevice*> sockets;
QMutex socketMutex;
QThreadStorage<Soprano::Client::SocketHandler*> socketStorage;
+#endif
};
}
}
diff --git a/client/clientmodel.cpp b/client/clientmodel.cpp
index c51219f..bdcbed3 100644
--- a/client/clientmodel.cpp
+++ b/client/clientmodel.cpp
@@ -50,7 +50,7 @@ Soprano::Client::ClientModel::~ClientModel()
// closed by the server anyway.
//
QMutexLocker locker( &m_openIteratorsMutex );
- if ( m_client->isConnectedInCurrentThread() ) {
+ if ( m_client->isConnected() ) {
for ( int i = 0; i < m_openIterators.count(); ++i ) {
m_client->iteratorClose( m_openIterators[i] );
}
diff --git a/client/localsocketclient.cpp b/client/localsocketclient.cpp
index ef91259..cea06bc 100644
--- a/client/localsocketclient.cpp
+++ b/client/localsocketclient.cpp
@@ -1,7 +1,7 @@
/*
* This file is part of Soprano Project.
*
- * Copyright (C) 2007-2008 Sebastian Trueg <trueg@kde.org>
+ * Copyright (C) 2007-2012 Sebastian Trueg <trueg@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,15 +22,18 @@
#include "localsocketclient.h"
#include "clientconnection.h"
#include "clientmodel.h"
+#include "socket.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QThread>
#include <QtNetwork/QLocalSocket>
+#ifdef Q_OS_WIN
Q_DECLARE_METATYPE( QLocalSocket::LocalSocketError )
Q_DECLARE_METATYPE( QAbstractSocket::SocketError )
Q_DECLARE_METATYPE( QAbstractSocket::SocketState )
+#endif
namespace Soprano {
namespace Client {
@@ -41,8 +44,10 @@ namespace Soprano {
~LocalSocketClientConnection();
protected:
- QIODevice* newConnection();
- bool isConnected( QIODevice* );
+ Socket *newConnection();
+#ifdef Q_OS_WIN
+ bool isConnected( Socket* );
+#endif
private:
QString m_socketPath;
@@ -58,7 +63,7 @@ namespace Soprano {
{
}
- QIODevice* LocalSocketClientConnection::newConnection()
+ Socket* LocalSocketClientConnection::newConnection()
{
clearError();
QString path( m_socketPath );
@@ -66,6 +71,14 @@ namespace Soprano {
path = QDir::homePath() + QLatin1String( "/.soprano/socket" );
}
+#ifndef Q_OS_WIN
+ LocalSocket* socket = new LocalSocket;
+ if ( socket->open( path ) ) {
+ return socket;
+ }
+ else {
+ setError( socket->lastError() );
+#else
QLocalSocket* socket = new QLocalSocket;
socket->connectToServer( path, QIODevice::ReadWrite );
if ( socket->waitForConnected() ) {
@@ -75,14 +88,17 @@ namespace Soprano {
}
else {
setError( socket->errorString() );
+#endif
delete socket;
return 0;
}
}
- bool LocalSocketClientConnection::isConnected( QIODevice* device ) {
+#ifdef Q_OS_WIN
+ bool LocalSocketClientConnection::isConnected( Socket *device ) {
return( device ? static_cast<QLocalSocket*>( device )->state() == QLocalSocket::ConnectedState : false );
}
+#endif
}
}
@@ -95,25 +111,28 @@ public:
}
LocalSocketClientConnection* connection;
-
+#ifdef Q_OS_WIN
void _s_localSocketError( QLocalSocket::LocalSocketError );
+#endif
};
-
+#ifdef Q_OS_WIN
void Soprano::Client::LocalSocketClient::Private::_s_localSocketError( QLocalSocket::LocalSocketError error )
{
qDebug() << "local socket error:" << error;
}
-
+#endif
Soprano::Client::LocalSocketClient::LocalSocketClient( QObject* parent )
: QObject( parent ),
d( new Private() )
{
+#ifdef Q_OS_WIN
qRegisterMetaType<QLocalSocket::LocalSocketError>();
qRegisterMetaType<QAbstractSocket::SocketError>();
qRegisterMetaType<QAbstractSocket::SocketState>();
+#endif
}
@@ -127,18 +146,9 @@ Soprano::Client::LocalSocketClient::~LocalSocketClient()
bool Soprano::Client::LocalSocketClient::connect( const QString& name )
{
if ( !isConnected() ) {
- //
- // trueg: This is a hack: we do not disconnect since we essentially re-connect
- // in every thread anyway. Thus, the whole connect/disconnect API is sort of a lie.
- // This is something that grew over time and needs to be fixed. The best solution
- // I see at the moment is to drop Qt for socket communication. QObject is just too
- // heavy for that.
- // Another solution would be for Soprano 3 to simply make the client non-thread-safe.
- // Then each client thread would need to create its own connection manually.
- //
if ( !d->connection )
d->connection = new LocalSocketClientConnection( name, this );
- if ( d->connection->connectInCurrentThread() &&
+ if ( d->connection->connect() &&
d->connection->checkProtocolVersion() ) {
return true;
}
@@ -149,14 +159,14 @@ bool Soprano::Client::LocalSocketClient::connect( const QString& name )
}
else {
setError( "Already connected" );
- return false;
+ return true;
}
}
bool Soprano::Client::LocalSocketClient::isConnected() const
{
- return d->connection ? d->connection->connectInCurrentThread() : false;
+ return d->connection ? d->connection->isConnected() : false;
}
diff --git a/client/localsocketclient.h b/client/localsocketclient.h
index d359679..a31c694 100644
--- a/client/localsocketclient.h
+++ b/client/localsocketclient.h
@@ -1,7 +1,7 @@
/*
* This file is part of Soprano Project.
*
- * Copyright (C) 2007-2008 Sebastian Trueg <trueg@kde.org>
+ * Copyright (C) 2007-2012 Sebastian Trueg <trueg@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -120,8 +120,9 @@ namespace Soprano {
private:
class Private;
Private* const d;
-
+#ifdef Q_OS_WIN
Q_PRIVATE_SLOT( d, void _s_localSocketError( QLocalSocket::LocalSocketError ) )
+#endif
};
}
}
diff --git a/client/socket.cpp b/client/socket.cpp
new file mode 100644
index 0000000..da547d9
--- /dev/null
+++ b/client/socket.cpp
@@ -0,0 +1,161 @@
+/*
+ * This file is part of Soprano Project.
+ *
+ * Copyright (C) 2010-2012 Sebastian Trueg <trueg@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "socket.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QDebug>
+
+Soprano::Socket::Socket( SOCKET_HANDLE fd )
+ : m_handle( fd ),
+ m_mutex( QMutex::Recursive )
+{
+}
+
+
+Soprano::Socket::~Socket()
+{
+}
+
+
+bool Soprano::Socket::isConnected() const
+{
+ return m_handle > 0;
+}
+
+
+void Soprano::Socket::close()
+{
+ if ( m_handle >= 0 ) {
+ ::close( m_handle );
+ m_handle = -1;
+ }
+}
+
+
+bool Soprano::Socket::waitForReadyRead( int timeout )
+{
+ if ( isConnected() ) {
+ fd_set fds;
+ FD_ZERO( &fds );
+ FD_SET( m_handle, &fds );
+
+ struct timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+ int r = ::select( m_handle + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
+ return r > 0;
+ }
+ else {
+ return false;
+ }
+}
+
+
+qint64 Soprano::Socket::read( char* buffer, qint64 max )
+{
+ qint64 r = ::read( m_handle, buffer, max );
+ if ( r < 0 ) {
+ setError( QString::fromLatin1( "Failed to read from fd %1 (%2)" ).arg( m_handle ).arg( QLatin1String( strerror( errno ) ) ) );
+ }
+ return r;
+}
+
+
+qint64 Soprano::Socket::write( const char* buffer, qint64 max )
+{
+ qint64 r = ::write( m_handle, buffer, max );
+ if ( r < 0 ) {
+ setError( QString::fromLatin1( "Failed to write to fd %1 (%2)" ).arg( m_handle ).arg( QLatin1String( strerror( errno ) ) ) );
+ }
+ return r;
+}
+
+
+void Soprano::Socket::lock()
+{
+ m_mutex.lock();
+}
+
+
+void Soprano::Socket::unlock()
+{
+ m_mutex.unlock();
+}
+
+
+
+Soprano::LocalSocket::LocalSocket()
+{
+}
+
+
+Soprano::LocalSocket::~LocalSocket()
+{
+}
+
+
+bool Soprano::LocalSocket::open( const QString& path )
+{
+ m_path = path;
+ return open();
+}
+
+
+bool Soprano::LocalSocket::open()
+{
+ // create a socket
+ m_handle = ::socket( AF_UNIX, SOCK_STREAM, 0 );
+ if ( m_handle < 0 ) {
+ setError( QString::fromLatin1( "Could not create socket (%1)" ).arg( strerror(errno) ) );
+ return false;
+ }
+
+ // set the address
+ struct sockaddr_un servAddr;
+ memset( &servAddr, 0, sizeof(servAddr) );
+ servAddr.sun_family = AF_UNIX;
+ QByteArray s = QFile::encodeName( m_path );
+ if ( s.length() > ( int )sizeof(servAddr.sun_path) + 1 ) {
+ setError( QLatin1String( "Not enough space to store socket path." ) );
+ ::close( m_handle );
+ m_handle = -1;
+ return false;
+ }
+ ::memcpy( servAddr.sun_path, s.data(), s.size()+1 );
+
+ // connect to the server
+ if ( ::connect( m_handle, (struct sockaddr *)&servAddr, sizeof( servAddr ) ) < 0 ) {
+ setError( QString::fromLatin1( "Could not connect to server at %1 (%2)" ).arg( m_path ).arg( strerror(errno) ) );
+ ::close( m_handle );
+ return false;
+ }
+
+ return true;
+}
diff --git a/client/socket.h b/client/socket.h
new file mode 100644
index 0000000..5cdc00b
--- /dev/null
+++ b/client/socket.h
@@ -0,0 +1,103 @@
+/*
+ * This file is part of Soprano Project.
+ *
+ * Copyright (C) 2010-2012 Sebastian Trueg <trueg@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _SOPRANO_SOCKET_H_
+#define _SOPRANO_SOCKET_H_
+
+#include "error.h"
+
+#include <QtCore/QMutex>
+
+typedef int SOCKET_HANDLE;
+
+namespace Soprano {
+#ifdef Q_OS_WIN
+ typedef QIODevice Socket;
+#else
+ /**
+ * A thread-safe socket without the QObject overhead of Qt's own socket
+ * implementations.
+ */
+ class Socket : public Error::ErrorCache
+ {
+ public:
+ /**
+ * Create a new socket.
+ * \param fd Allows to create a wrapper around the fd to
+ * read and write from and to it.
+ */
+ Socket( SOCKET_HANDLE fd = -1 );
+ virtual ~Socket();
+
+ SOCKET_HANDLE handle() const { return m_handle; }
+
+ /**
+ * Returns true of the socket has successfully been opened.
+ * Does not actually check the connection. Thus, if the
+ * connection is closed remotely this method does not notice it.
+ */
+ virtual bool isConnected() const;
+
+ virtual void close();
+
+ virtual bool waitForReadyRead( int timeout = -1 );
+
+ virtual qint64 read( char* buffer, qint64 max );
+ virtual qint64 write( const char* buffer, qint64 max );
+
+ /// lock the socket (no other thread can use it)
+ void lock();
+
+ /// unlock the socket
+ void unlock();
+
+ protected:
+ /**
+ * Open the socket with the last config. Used
+ * for automatic reconnect.
+ */
+ virtual bool open() {
+ return false;
+ }
+
+ SOCKET_HANDLE m_handle;
+
+ private:
+ QMutex m_mutex;
+ };
+
+ class LocalSocket : public Socket
+ {
+ public:
+ LocalSocket();
+ ~LocalSocket();
+
+ bool open( const QString& path );
+
+ private:
+ bool open();
+
+ QString m_path;
+ };
+#endif
+}
+
+#endif
diff --git a/client/socketstream.cpp b/client/socketstream.cpp
new file mode 100644
index 0000000..dfd8713
--- /dev/null
+++ b/client/socketstream.cpp
@@ -0,0 +1,567 @@
+/*
+ * This file is part of Soprano Project.
+ *
+ * Copyright (C) 2008-2012 Sebastian Trueg <trueg@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "socketstream.h"
+
+#include "node.h"
+#include "statement.h"
+#include "bindingset.h"
+#include "backend.h"
+#include "literalvalue.h"
+#include "locator.h"
+#include "languagetag.h"
+
+
+Soprano::SocketStream::SocketStream( Soprano::Socket* dev )
+ : m_device( dev )
+{
+#ifndef Q_OS_WIN
+ m_device->lock();
+#endif
+}
+
+
+Soprano::SocketStream::~SocketStream()
+{
+#ifndef Q_OS_WIN
+ m_device->unlock();
+#endif
+}
+
+
+bool Soprano::SocketStream::writeByteArray( const QByteArray& a )
+{
+ quint32 len = a.length();
+
+ if ( !writeUnsignedInt32( len ) ) {
+ return false;
+ }
+
+ quint32 cnt = 0;
+ while ( cnt < len ) {
+ int x = qMin( 1024U, len-cnt );
+ int r = m_device->write( a.data()+cnt, x );
+ if ( r < 0 ) {
+#ifdef Q_OS_WIN
+ setError( Error::Error( QString( "Failed to write string after %1 of %2 bytes (%3)." ).arg( cnt ).arg( len ).arg( m_device->errorString() ) ) );
+#else
+ setError(m_device->lastError());
+#endif
+ return false;
+ }
+ cnt += r;
+ }
+
+ clearError();
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeString( const QString& s )
+{
+ // FIXME: Optimize this by directly encoding QChars just like operator<< does
+ return writeByteArray( s.toUtf8() );
+}
+
+
+bool Soprano::SocketStream::writeUrl( const QUrl& url )
+{
+ return writeByteArray( url.toEncoded() );
+}
+
+
+bool Soprano::SocketStream::writeUnsignedInt8( quint8 v )
+{
+ if ( !m_device || m_device->write( (char*)&v, 1 ) != 1 ) {
+ setError( "Failed to write unsigned int8." );
+ return false;
+ }
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeUnsignedInt16( quint16 v )
+{
+ if ( !m_device || m_device->write( (char*)&v, 2 ) != 2 ) {
+ setError( "Failed to write unsigned int32." );
+ return false;
+ }
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeUnsignedInt32( quint32 v )
+{
+ if ( !m_device || m_device->write( (char*)&v, sizeof( quint32 ) ) != sizeof( quint32 ) ) {
+ setError( "Failed to write unsigned int32." );
+ return false;
+ }
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeInt32( qint32 v )
+{
+ if ( !m_device || m_device->write( (char*)&v, sizeof( qint32 ) ) != sizeof( qint32 ) ) {
+ setError( "Failed to write int32." );
+ return false;
+ }
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeErrorCode( Error::ErrorCode code )
+{
+ return writeUnsignedInt16( ( quint16 )code );
+}
+
+
+bool Soprano::SocketStream::writeBool( bool v )
+{
+ return writeUnsignedInt8( ( quint8 )v );
+}
+
+
+bool Soprano::SocketStream::writeLocator( const Error::Locator& loc )
+{
+ return( writeInt32( ( qint32 )loc.line() ) &&
+ writeInt32( ( qint32 )loc.column() ) &&
+ writeInt32( ( qint32 )loc.byte() ) &&
+ writeString( loc.fileName() ) );
+}
+
+
+bool Soprano::SocketStream::writeError( const Error::Error& error )
+{
+ if ( !writeBool( error.isParserError() ) ||
+ !writeInt32( ( qint32 )error.code() ) ||
+ !writeString( error.message() ) ) {
+ return false;
+ }
+
+ if ( error.isParserError() ) {
+ Soprano::Error::ParserError e( error );
+ if ( !writeLocator( e.locator() ) ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// bool Soprano::SocketStream::writeBackendSetting( const BackendSetting& setting )
+// {
+// return ( writeUnsignedInt16( ( quint16 )setting.option() ) &&
+// writeString( setting.userOptionName() ) &&
+// writeVariant( setting.value() ) );
+// }
+
+
+bool Soprano::SocketStream::writeLiteralValue( const LiteralValue& value )
+{
+ if ( !writeBool( value.isPlain() ) ) {
+ return false;
+ }
+ if ( value.isPlain() ) {
+ return( writeString( value.toString() ) &&
+ writeString( value.language().toString() ) );
+ }
+ else {
+ return( writeString( value.toString() ) &&
+ writeUrl( value.dataTypeUri() ) );
+ }
+}
+
+
+bool Soprano::SocketStream::writeNode( const Node& node )
+{
+ if ( !writeUnsignedInt8( ( quint8 )node.type() ) ) {
+ return false;
+ }
+
+ if ( node.type() == Soprano::Node::LiteralNode ) {
+ if ( !writeLiteralValue( node.literal() ) ) {
+ return false;
+ }
+ }
+ else if ( node.type() == Soprano::Node::ResourceNode ) {
+ if ( !writeUrl( node.uri() ) ) {
+ return false;
+ }
+ }
+ else if ( node.type() == Soprano::Node::BlankNode ) {
+ if ( !writeString( node.identifier() ) ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeStatement( const Statement& s )
+{
+ if ( !writeNode( s.subject() ) ||
+ !writeNode( s.predicate() ) ||
+ !writeNode( s.object() ) ||
+ !writeNode( s.context() ) ) {
+ return false;
+ }
+ return true;
+}
+
+
+bool Soprano::SocketStream::writeBindingSet( const BindingSet& set )
+{
+ QStringList bn = set.bindingNames();
+ if ( !writeUnsignedInt32( ( quint32 )bn.count() ) ) {
+ return false;
+ }
+ for ( int i = 0; i < set.count(); ++i ) {
+ if ( !writeString( bn[i] ) ||
+ !writeNode( set[i] ) ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool Soprano::SocketStream::read( char* data, qint64 size )
+{
+ qint64 cnt = 0;
+ while ( cnt < size ) {
+ qint64 m = qMin( size-cnt, 1024LL );
+ qint64 r = m_device->read( data+cnt, m );
+ if ( r < 0 ) {
+ setError( Error::Error( QString( "Failed to read after %1 of %2 bytes (%3)." )
+ .arg( cnt )
+ .arg( size )
+#ifdef Q_OS_WIN
+ .arg( m_device->errorString ) ) );
+#else
+ .arg( m_device->lastError().message() ) ) );
+#endif
+ return false;
+ }
+ else if ( r == 0 && size > 0 ) {
+ if ( !m_device->waitForReadyRead( 30000 ) ) {
+ setError( Error::Error( QString( "Timeout when reading after %1 of %2 bytes (%3)." )
+ .arg( cnt )
+ .arg( size )
+#ifdef Q_OS_WIN
+ .arg( m_device->errorString ) ) );
+#else
+ .arg( m_device->lastError().message() ) ) );
+#endif
+ return false;
+ }
+ }
+
+ cnt += r;
+ }
+
+ clearError();
+ return true;
+}
+
+
+bool Soprano::SocketStream::readByteArray( QByteArray& a )
+{
+ quint32 len;
+ if ( !readUnsignedInt32( len ) ) {
+ return false;
+ }
+
+ a.resize( len );
+
+ return read( a.data(), len );
+}
+
+
+bool Soprano::SocketStream::readString( QString& s )
+{
+ QByteArray a;
+ if ( readByteArray( a ) ) {
+ s = QString::fromUtf8( a );
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool Soprano::SocketStream::readUrl( QUrl& url )
+{
+ QByteArray a;
+ if ( readByteArray( a ) ) {
+ url = QUrl::fromEncoded( a, QUrl::StrictMode );
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool Soprano::SocketStream::readUnsignedInt8( quint8& i )
+{
+ if ( !read( ( char* )&i, 1 ) ) {
+ i = 0;
+ setError( "Failed to read unsigned int8" );
+ return false;
+ }
+ else {
+ clearError();
+ return true;
+ }
+}
+
+
+bool Soprano::SocketStream::readUnsignedInt16( quint16& i )
+{
+ if ( !read( (char*)&i, 2 ) ) {
+ i = 0;
+ setError( "Failed to read unsigned int16" );
+ return false;
+ }
+ else {
+ clearError();
+ return true;
+ }
+}
+
+
+bool Soprano::SocketStream::readUnsignedInt32( quint32& i )
+{
+ if ( !read( (char*)&i, 4 ) ) {
+ i = 0;
+ setError( "Failed to read unsigned int32" );
+ return false;
+ }
+ else {
+ clearError();
+ return true;
+ }
+}
+
+
+bool Soprano::SocketStream::readInt32( qint32& i )
+{
+ if ( !read( (char*)&i, 4 ) ) {
+ i = 0;
+ setError( "Failed to read int32" );
+ return false;
+ }
+ else {
+ clearError();
+ return true;
+ }
+}
+
+
+bool Soprano::SocketStream::readErrorCode( Error::ErrorCode& code )
+{
+ quint16 v;
+ if ( readUnsignedInt16( v ) ) {
+ code = Error::convertErrorCode( v );
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool Soprano::SocketStream::readBool( bool& b )
+{
+ quint8 v;
+ if ( readUnsignedInt8( v ) ) {
+ b = v;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool Soprano::SocketStream::readLocator( Error::Locator& loc )
+{
+ qint32 line, column, byte;
+ QString fileName;
+ if ( readInt32( line ) &&
+ readInt32( column ) &&
+ readInt32( byte ) &&
+ readString( fileName ) ) {
+ loc = Soprano::Error::Locator( line, column, byte, fileName );
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool Soprano::SocketStream::readError( Error::Error& error )
+{
+ bool isParserError = false;
+ QString message;
+ qint32 code;
+ if ( !readBool( isParserError ) ||
+ !readInt32( code ) ||
+ !readString( message ) ) {
+ return false;
+ }
+
+ if ( isParserError ) {
+ Soprano::Error::Locator loc;
+ if ( !readLocator( loc ) ) {
+ return false;
+ }
+ error = Soprano::Error::ParserError( loc, message, code );
+ }
+ else {
+ error = Soprano::Error::Error( message, code );
+ }
+ return true;
+}
+
+
+// bool Soprano::SocketStream::readBackendSetting( BackendSetting& setting )
+// {
+// quint16 option;
+// QString userOption;
+// QVariant value;
+// if ( readUnsignedInt16( option ) &&
+// readString( userOption ) &&
+// readVariant( value ) ) {
+// if ( option == Soprano::BackendOptionUser ) {
+// setting = Soprano::BackendSetting( userOption, value );
+// }
+// else {
+// setting = Soprano::BackendSetting( ( Soprano::BackendOption )option, value );
+// }
+// return true;
+// }
+// else {
+// return false;
+// }
+// }
+
+
+bool Soprano::SocketStream::readLiteralValue( LiteralValue& val )
+{
+ bool plain;
+ if ( readBool( plain ) ) {
+ QString v;
+ if ( plain ) {
+ QString lang;
+ if ( readString( v ) &&
+ readString( lang ) ) {
+ val = LiteralValue::createPlainLiteral( v, lang );
+ return true;
+ }
+ }
+ else {
+ QUrl dt;
+ if ( readString( v ) &&
+ readUrl( dt ) ) {
+ val = LiteralValue::fromString( v, dt );
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+bool Soprano::SocketStream::readNode( Node& node )
+{
+ quint8 type;
+ if ( !readUnsignedInt8( type ) ) {
+ return false;
+ }
+ if ( type == Soprano::Node::LiteralNode ) {
+ Soprano::LiteralValue v;
+ if ( !readLiteralValue( v ) ) {
+ return false;
+ }
+ node = v;
+ }
+ else if ( type == Soprano::Node::ResourceNode ) {
+ QUrl url;
+ if ( !readUrl( url ) ) {
+ return false;
+ }
+ node = Soprano::Node( url );
+ }
+ else if ( type == Soprano::Node::BlankNode ) {
+ QString id;
+ if ( !readString( id ) ) {
+ return false;
+ }
+ node = Soprano::Node( id );
+ }
+ else {
+ node = Soprano::Node();
+ }
+
+ return true;
+}
+
+
+bool Soprano::SocketStream::readStatement( Statement& s )
+{
+ Soprano::Node subject, predicate, object, context;
+ if ( readNode( subject ) &&
+ readNode( predicate ) &&
+ readNode( object ) &&
+ readNode( context ) ) {
+ s = Statement( subject, predicate, object, context );
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool Soprano::SocketStream::readBindingSet( BindingSet& set )
+{
+ set = BindingSet();
+ quint32 nb;
+ if ( !readUnsignedInt32( nb ) ) {
+ return false;
+ }
+ for ( quint32 i = 0; i < nb; ++i ) {
+ QString name;
+ Node node;
+ if ( !readString( name ) ||
+ !readNode( node ) ) {
+ return false;
+ }
+ set.insert( name, node );
+ }
+ return true;
+}
diff --git a/client/socketstream.h b/client/socketstream.h
new file mode 100644
index 0000000..a7b1eb2
--- /dev/null
+++ b/client/socketstream.h
@@ -0,0 +1,108 @@
+/*
+ * This file is part of Soprano Project.
+ *
+ * Copyright (C) 2008-2012 Sebastian Trueg <trueg@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _SOPRANO_SOCKET_STREAM_H_
+#define _SOPRANO_SOCKET_STREAM_H_
+
+#include "error.h"
+#include "socket.h"
+
+class QUrl;
+class QByteArray;
+
+namespace Soprano {
+
+ class LiteralValue;
+ class BindingSet;
+ class BackendSetting;
+ class Node;
+ class Statement;
+ namespace Error {
+ class Locator;
+ }
+
+ /**
+ * Provides streaming methods for all %Soprano
+ * types. Compared to QDataStream's operators
+ * it provides error handling and automatically
+ * fills the buffer if more data needs to be
+ * requested (QIODevice::waitForReadyRead)
+ *
+ * \author Sebastian Trueg <trueg@kde.org>
+ */
+ class SocketStream : public Error::ErrorCache
+ {
+ public:
+ SocketStream( Socket* dev );
+ ~SocketStream();
+
+ bool writeByteArray( const QByteArray& );
+ bool writeString( const QString& );
+ bool writeUrl( const QUrl& );
+// bool writeVariant( const QVariant& );
+ bool writeUnsignedInt8( quint8 );
+ bool writeUnsignedInt16( quint16 );
+ bool writeUnsignedInt32( quint32 );
+ bool writeInt32( qint32 );
+ bool writeBool( bool );
+
+ bool writeErrorCode( Error::ErrorCode code );
+ bool writeLocator( const Error::Locator& );
+ bool writeError( const Error::Error& );
+// bool writeBackendSetting( const BackendSetting& );
+ bool writeLiteralValue( const LiteralValue& );
+ bool writeNode( const Node& );
+ bool writeStatement( const Statement& );
+ bool writeBindingSet( const BindingSet& );
+
+ bool readByteArray( QByteArray& );
+ bool readString( QString& );
+ bool readUrl( QUrl& );
+// bool readVariant( QVariant& );
+ bool readUnsignedInt8( quint8& );
+ bool readUnsignedInt16( quint16& );
+ bool readUnsignedInt32( quint32& );
+ bool readInt32( qint32& );
+ bool readBool( bool& );
+
+ bool readErrorCode( Error::ErrorCode& code );
+ bool readLocator( Error::Locator& );
+ bool readError( Error::Error& );
+// bool readBackendSetting( BackendSetting& );
+ bool readLiteralValue( LiteralValue& );
+ bool readNode( Node& );
+ bool readStatement( Statement& );
+ bool readBindingSet( BindingSet& );
+
+ private:
+ /**
+ * Read from the device including waiting for data
+ * to be ready.
+ *
+ * \sa Socket::read, Socket::waitForReadyRead
+ */
+ bool read( char* data, qint64 size );
+
+ Socket* m_device;
+ };
+}
+
+#endif
diff --git a/client/tcpclient.cpp b/client/tcpclient.cpp
index 69329da..796ca59 100644
--- a/client/tcpclient.cpp
+++ b/client/tcpclient.cpp
@@ -117,7 +117,7 @@ bool Soprano::Client::TcpClient::connect( const QHostAddress& address, int port
if ( !isConnected() ) {
if ( !d->connection )
d->connection = new TcpClientConnection( address, port, this );
- if ( d->connection->connectInCurrentThread() &&
+ if ( d->connection->connect() &&
d->connection->checkProtocolVersion() ) {
return true;
}
@@ -135,7 +135,7 @@ bool Soprano::Client::TcpClient::connect( const QHostAddress& address, int port
bool Soprano::Client::TcpClient::isConnected()
{
- return d->connection ? d->connection->isConnectedInCurrentThread() : false;
+ return d->connection ? d->connection->isConnected() : false;
}