* QtLockedFile: Locking file needs this class. This class is in Qt developpers website: http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtlockedfile/
* threadedTcpSocket: This is tcpSocket class that run in non-main thread.
ui/settingdialog.h
ui/rtfeditor.h
)
+#set(file_h file/qtlockedfile.h)
#Ui files
set(ui
ui/settingdialog.cxx
ui/rtfeditor.cxx
)
+set(file_impl file/qtlockedfile.cxx)
+set(file_win32 file/qtlockedfile_win.cxx)
+set(file_unix file/qtlockedfile_unix.cxx)
#resource files
set(res
)
qt4_wrap_cpp(network_moc ${network_h})
-
+#qt4_wrap_cpp(file_moc ${file_h})
qt4_wrap_cpp(ui_moc ${ui_h})
qt4_wrap_ui(ui_moc ${ui})
qt4_add_resources(res_moc ${res})
add_executable(jasmine WIN32
${main} ${ui_moc} ${ui_src} ${network_moc}
${network_src} ${structures} ${res_moc}
- ${validator} ${ported_rmd6})
+ ${validator} ${ported_rmd6} ${file_win32}
+ ${file_impl})
set_property(TARGET jasmine PROPERTY COMPLILE_FLAGS ${OpenMP_CXX_FLAGS} APPEND)
target_link_libraries(jasmine gomp ${QT_LIBRARIES})
else(OPENMP_FOUND)
add_executable(jasmine WIN32
${main} ${ui_moc} ${ui_src} ${network_moc}
${network_src} ${structures} ${res_moc}
- ${validator} ${ported_rmd6})
+ ${validator} ${ported_rmd6} ${file_win32} ${file_impl})
target_link_libraries(jasmine ${QT_LIBRARIES})
endif(OPENMP_FOUND)
else(WIN32)
add_library(network SHARED ${network_moc} ${network_src})
add_library(ui SHARED ${ui_moc} ${ui_src})
+ add_library(file SHARED ${file_unix} ${file_impl})
add_executable(jasmine ${main})
target_link_libraries(validator ${QT_LIBRARIES})
target_link_libraries(resource ${QT_LIBRARIES})
target_link_libraries(structures ${QT_LIBRARIES})
+ target_link_libraries(file ${QT_LIBRARIES})
target_link_libraries(structures qripemd160 ${QT_LIBRARIES})
- target_link_libraries(network structures validator ${QT_LIBRARIES})
- target_link_libraries(ui resource network ${QT_LIBRARIES})
+ target_link_libraries(network structures validator file ${QT_LIBRARIES})
+ target_link_libraries(ui resource network file ${QT_LIBRARIES})
target_link_libraries(jasmine ui ${QT_LIBRARIES})
if(OPENMP_FOUND)
--- /dev/null
+#include "qtlockedfile.h"
--- /dev/null
+/****************************************************************************
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of a Qt Solutions component.
+**
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Solutions Commercial License Agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** Please note Third Party Software included with Qt Solutions may impose
+** additional restrictions and it is the user's responsibility to ensure
+** that they have met the licensing requirements of the GPL, LGPL, or Qt
+** Solutions Commercial license and the relevant license of the Third
+** Party Software they are using.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+#include "qtlockedfile.h"
+
+/*!
+ \class QtLockedFile
+
+ \brief The QtLockedFile class extends QFile with advisory locking
+ functions.
+
+ A file may be locked in read or write mode. Multiple instances of
+ \e QtLockedFile, created in multiple processes running on the same
+ machine, may have a file locked in read mode. Exactly one instance
+ may have it locked in write mode. A read and a write lock cannot
+ exist simultaneously on the same file.
+
+ The file locks are advisory. This means that nothing prevents
+ another process from manipulating a locked file using QFile or
+ file system functions offered by the OS. Serialization is only
+ guaranteed if all processes that access the file use
+ QLockedFile. Also, while holding a lock on a file, a process
+ must not open the same file again (through any API), or locks
+ can be unexpectedly lost.
+
+ The lock provided by an instance of \e QtLockedFile is released
+ whenever the program terminates. This is true even when the
+ program crashes and no destructors are called.
+*/
+
+/*! \enum QtLockedFile::LockMode
+
+ This enum describes the available lock modes.
+
+ \value ReadLock A read lock.
+ \value WriteLock A write lock.
+ \value NoLock Neither a read lock nor a write lock.
+*/
+
+/*!
+ Constructs an unlocked \e QtLockedFile object. This constructor
+ behaves in the same way as \e QFile::QFile().
+
+ \sa QFile::QFile()
+*/
+QtLockedFile::QtLockedFile()
+ : QFile()
+{
+#ifdef Q_OS_WIN
+ wmutex = 0;
+ rmutex = 0;
+#endif
+ m_lock_mode = NoLock;
+}
+
+/*!
+ Constructs an unlocked QtLockedFile object with file \a name. This
+ constructor behaves in the same way as \e QFile::QFile(const
+ QString&).
+
+ \sa QFile::QFile()
+*/
+QtLockedFile::QtLockedFile(const QString &name)
+ : QFile(name)
+{
+#ifdef Q_OS_WIN
+ wmutex = 0;
+ rmutex = 0;
+#endif
+ m_lock_mode = NoLock;
+}
+
+/*!
+ Opens the file in OpenMode \a mode.
+
+ This is identical to QFile::open(), with the one exception that the
+ Truncate mode flag is disallowed. Truncation would conflict with the
+ advisory file locking, since the file would be modified before the
+ write lock is obtained. If truncation is required, use resize(0)
+ after obtaining the write lock.
+
+ Returns true if successful; otherwise false.
+
+ \sa QFile::open(), QFile::resize()
+*/
+bool QtLockedFile::open(OpenMode mode)
+{
+ if (mode & QIODevice::Truncate) {
+ qWarning("QtLockedFile::open(): Truncate mode not allowed.");
+ return false;
+ }
+ return QFile::open(mode);
+}
+
+/*!
+ Returns \e true if this object has a in read or write lock;
+ otherwise returns \e false.
+
+ \sa lockMode()
+*/
+bool QtLockedFile::isLocked() const
+{
+ return m_lock_mode != NoLock;
+}
+
+/*!
+ Returns the type of lock currently held by this object, or \e
+ QtLockedFile::NoLock.
+
+ \sa isLocked()
+*/
+QtLockedFile::LockMode QtLockedFile::lockMode() const
+{
+ return m_lock_mode;
+}
+
+/*!
+ \fn bool QtLockedFile::lock(LockMode mode, bool block = true)
+
+ Obtains a lock of type \a mode. The file must be opened before it
+ can be locked.
+
+ If \a block is true, this function will block until the lock is
+ aquired. If \a block is false, this function returns \e false
+ immediately if the lock cannot be aquired.
+
+ If this object already has a lock of type \a mode, this function
+ returns \e true immediately. If this object has a lock of a
+ different type than \a mode, the lock is first released and then a
+ new lock is obtained.
+
+ This function returns \e true if, after it executes, the file is
+ locked by this object, and \e false otherwise.
+
+ \sa unlock(), isLocked(), lockMode()
+*/
+
+/*!
+ \fn bool QtLockedFile::unlock()
+
+ Releases a lock.
+
+ If the object has no lock, this function returns immediately.
+
+ This function returns \e true if, after it executes, the file is
+ not locked by this object, and \e false otherwise.
+
+ \sa lock(), isLocked(), lockMode()
+*/
+
+/*!
+ \fn QtLockedFile::~QtLockedFile()
+
+ Destroys the \e QtLockedFile object. If any locks were held, they
+ are released.
+*/
--- /dev/null
+/****************************************************************************
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of a Qt Solutions component.
+**
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Solutions Commercial License Agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** Please note Third Party Software included with Qt Solutions may impose
+** additional restrictions and it is the user's responsibility to ensure
+** that they have met the licensing requirements of the GPL, LGPL, or Qt
+** Solutions Commercial license and the relevant license of the Third
+** Party Software they are using.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+#ifndef QTLOCKEDFILE_H
+#define QTLOCKEDFILE_H
+
+#include <QtCore/QFile>
+#ifdef Q_OS_WIN
+#include <QtCore/QVector>
+#endif
+
+#if defined(Q_WS_WIN)
+# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
+# define QT_QTLOCKEDFILE_EXPORT
+# elif defined(QT_QTLOCKEDFILE_IMPORT)
+# if defined(QT_QTLOCKEDFILE_EXPORT)
+# undef QT_QTLOCKEDFILE_EXPORT
+# endif
+# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
+# elif defined(QT_QTLOCKEDFILE_EXPORT)
+# undef QT_QTLOCKEDFILE_EXPORT
+# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
+# endif
+#else
+# define QT_QTLOCKEDFILE_EXPORT
+#endif
+
+class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
+{
+public:
+ enum LockMode { NoLock = 0, ReadLock, WriteLock };
+
+ QtLockedFile();
+ QtLockedFile(const QString &name);
+ ~QtLockedFile();
+
+ bool open(OpenMode mode);
+
+ bool lock(LockMode mode, bool block = true);
+ bool unlock();
+ bool isLocked() const;
+ LockMode lockMode() const;
+
+private:
+#ifdef Q_OS_WIN
+ Qt::HANDLE wmutex;
+ Qt::HANDLE rmutex;
+ QVector<Qt::HANDLE> rmutexes;
+ QString mutexname;
+
+ Qt::HANDLE getMutexHandle(int idx, bool doCreate);
+ bool waitMutex(Qt::HANDLE mutex, bool doBlock);
+
+#endif
+ LockMode m_lock_mode;
+};
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of a Qt Solutions component.
+**
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Solutions Commercial License Agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** Please note Third Party Software included with Qt Solutions may impose
+** additional restrictions and it is the user's responsibility to ensure
+** that they have met the licensing requirements of the GPL, LGPL, or Qt
+** Solutions Commercial license and the relevant license of the Third
+** Party Software they are using.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "qtlockedfile.h"
+
+bool QtLockedFile::lock(LockMode mode, bool block)
+{
+ if (!isOpen()) {
+ qWarning("QtLockedFile::lock(): file is not opened");
+ return false;
+ }
+
+ if (mode == NoLock)
+ return unlock();
+
+ if (mode == m_lock_mode)
+ return true;
+
+ if (m_lock_mode != NoLock)
+ unlock();
+
+ struct flock fl;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
+ int cmd = block ? F_SETLKW : F_SETLK;
+ int ret = fcntl(handle(), cmd, &fl);
+
+ if (ret == -1) {
+ if (errno != EINTR && errno != EAGAIN)
+ qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
+ return false;
+ }
+
+
+ m_lock_mode = mode;
+ return true;
+}
+
+
+bool QtLockedFile::unlock()
+{
+ if (!isOpen()) {
+ qWarning("QtLockedFile::unlock(): file is not opened");
+ return false;
+ }
+
+ if (!isLocked())
+ return true;
+
+ struct flock fl;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_type = F_UNLCK;
+ int ret = fcntl(handle(), F_SETLKW, &fl);
+
+ if (ret == -1) {
+ qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
+ return false;
+ }
+
+ m_lock_mode = NoLock;
+ return true;
+}
+
+QtLockedFile::~QtLockedFile()
+{
+ if (isOpen())
+ unlock();
+}
+
--- /dev/null
+/****************************************************************************
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of a Qt Solutions component.
+**
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Solutions Commercial License Agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** Please note Third Party Software included with Qt Solutions may impose
+** additional restrictions and it is the user's responsibility to ensure
+** that they have met the licensing requirements of the GPL, LGPL, or Qt
+** Solutions Commercial license and the relevant license of the Third
+** Party Software they are using.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact Nokia at qt-info@nokia.com.
+**
+****************************************************************************/
+
+#include "qtlockedfile.h"
+#include <qt_windows.h>
+#include <QtCore/QFileInfo>
+
+#define MUTEX_PREFIX "QtLockedFile mutex "
+// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
+#define MAX_READERS MAXIMUM_WAIT_OBJECTS
+
+Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
+{
+ if (mutexname.isEmpty()) {
+ QFileInfo fi(*this);
+ mutexname = QString::fromLatin1(MUTEX_PREFIX)
+ + fi.absoluteFilePath().toLower();
+ }
+ QString mname(mutexname);
+ if (idx >= 0)
+ mname += QString::number(idx);
+
+ Qt::HANDLE mutex;
+ if (doCreate) {
+ QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
+ { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
+ if (!mutex) {
+ qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
+ return 0;
+ }
+ }
+ else {
+ QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
+ { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
+ if (!mutex) {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
+ return 0;
+ }
+ }
+ return mutex;
+}
+
+bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
+{
+ Q_ASSERT(mutex);
+ DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
+ switch (res) {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ return true;
+ break;
+ case WAIT_TIMEOUT:
+ break;
+ default:
+ qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
+ }
+ return false;
+}
+
+
+
+bool QtLockedFile::lock(LockMode mode, bool block)
+{
+ if (!isOpen()) {
+ qWarning("QtLockedFile::lock(): file is not opened");
+ return false;
+ }
+
+ if (mode == NoLock)
+ return unlock();
+
+ if (mode == m_lock_mode)
+ return true;
+
+ if (m_lock_mode != NoLock)
+ unlock();
+
+ if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
+ return false;
+
+ if (!waitMutex(wmutex, block))
+ return false;
+
+ if (mode == ReadLock) {
+ int idx = 0;
+ for (; idx < MAX_READERS; idx++) {
+ rmutex = getMutexHandle(idx, false);
+ if (!rmutex || waitMutex(rmutex, false))
+ break;
+ CloseHandle(rmutex);
+ }
+ bool ok = true;
+ if (idx >= MAX_READERS) {
+ qWarning("QtLockedFile::lock(): too many readers");
+ rmutex = 0;
+ ok = false;
+ }
+ else if (!rmutex) {
+ rmutex = getMutexHandle(idx, true);
+ if (!rmutex || !waitMutex(rmutex, false))
+ ok = false;
+ }
+ if (!ok && rmutex) {
+ CloseHandle(rmutex);
+ rmutex = 0;
+ }
+ ReleaseMutex(wmutex);
+ if (!ok)
+ return false;
+ }
+ else {
+ Q_ASSERT(rmutexes.isEmpty());
+ for (int i = 0; i < MAX_READERS; i++) {
+ Qt::HANDLE mutex = getMutexHandle(i, false);
+ if (mutex)
+ rmutexes.append(mutex);
+ }
+ if (rmutexes.size()) {
+ DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
+ TRUE, block ? INFINITE : 0);
+ if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
+ if (res != WAIT_TIMEOUT)
+ qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
+ m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
+ unlock();
+ return false;
+ }
+ }
+ }
+
+ m_lock_mode = mode;
+ return true;
+}
+
+bool QtLockedFile::unlock()
+{
+ if (!isOpen()) {
+ qWarning("QtLockedFile::unlock(): file is not opened");
+ return false;
+ }
+
+ if (!isLocked())
+ return true;
+
+ if (m_lock_mode == ReadLock) {
+ ReleaseMutex(rmutex);
+ CloseHandle(rmutex);
+ rmutex = 0;
+ }
+ else {
+ foreach(Qt::HANDLE mutex, rmutexes) {
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+ }
+ rmutexes.clear();
+ ReleaseMutex(wmutex);
+ }
+
+ m_lock_mode = QtLockedFile::NoLock;
+ return true;
+}
+
+QtLockedFile::~QtLockedFile()
+{
+ if (isOpen())
+ unlock();
+ if (wmutex)
+ CloseHandle(wmutex);
+}
res \
network \
ported_rmd6 \
+ file \
INCLUDEPATH \
+= \
.
network/tcpnetwork.h \
app_version.h \
settings.h \
- definition.h
+ definition.h \
+ file/QtLockedFile \
+ file/qtlockedfile.h
FORMS += ui/uifiles/about.ui \
ui/uifiles/jasmine_main.ui \
ui/uifiles/settings.ui
validator/ipaddressvalidator.cxx \
structures/header.cxx \
network/tcpnetwork.cxx \
+ file/qtlockedfile.cxx \
settings.cxx \
main.cxx
+
+unix:SOURCES+=file/qtlockedfile_unix.cxx
+win32:SOURCES+=file/qtlockedfile_win.cxx
QString Non_public_title(QObject::tr("Warning! This software is not public version!")),
Non_public_body(QObject::tr("This software is not public version. So, please note that many bugs may exist and many features are not implemented."));
-//I will implement i18n. Unfortunately, I have no time because I'm studying third language, researching japanese ideology, and so on.
int main(int argc,char* argv[]){
QApplication app(argc,argv);
+ app.setApplicationName("jasmine");
+ app.setApplicationVersion(QString("Gen.%1 Rev.%2").arg(gen).arg(rev));
+ QTranslator translator;
+ translator.load(app.applicationName()+"-"+QLocale::system().name(),qApp->applicationDirPath()+"/translators");
+ app.installTranslator(&translator);
mainWindow window;
if(rev==0) QMessageBox::warning(NULL,Non_public_title,Non_public_body);
QFileInfo memberlist(default_memberlist),setting(default_setting);
using namespace structures;
using namespace std;
tcpServer::tcpServer(quint64 buffersize, QObject *parent):QTcpServer(parent){this->buffersize=buffersize;}
+
void tcpServer::incomingConnection(int handle){
tcpSocket *socket=new tcpSocket(this->buffersize,this);
-
if(!socket->setSocketDescriptor(handle)){
emit this->socket_error(*socket);
- delete socket;
return;
}
- emit (emit this->pending(*socket))?this->newConnection():socket->abort();
+ if(emit this->pending(*socket)) this->newConnection();
+ else socket->abort();
+}
+
+threadedTcpSocket::threadedTcpSocket(int descriptor, quint64 buffersize, QObject *parent):QThread(parent){
+ this->handle=descriptor;
+ this->buffersize=buffersize;
+ this->mode=threadedTcpSocket::receive;
+ this->locker=new QReadWriteLock(QReadWriteLock::Recursive);
+ this->start();
+}
+threadedTcpSocket::threadedTcpSocket(const QString &senderName, const AddressAndPort &to,quint64 buffersize, QObject *parent):QThread(parent){
+ this->senderName=senderName;
+ this->buffersize=buffersize;
+ this->mode=threadedTcpSocket::send;
+ this->to=to;
+ this->locker=new QReadWriteLock(QReadWriteLock::Recursive);
+ this->start();
+}
+QString threadedTcpSocket::errorString() const{
+ return this->eStr;
+}
+void threadedTcpSocket::getErrorStringAndEmitError(const QAbstractSocket::SocketError &error){
+ tcpSocket *socket=qobject_cast<tcpSocket *>(this->sender());
+ this->eStr=socket->errorString();
+ emit this->error(error);
+}
+
+void threadedTcpSocket::connect_function(tcpSocket *socket){
+ Qt::ConnectionType connection=Qt::BlockingQueuedConnection;
+ connect(socket,SIGNAL(file_pending()),SIGNAL(file_pending()),connection);
+ connect(socket,
+ SIGNAL(fileStream_openFailed(const QFile::FileError &,const QString &)),
+ SIGNAL(fileStream_openFailed(const QFile::FileError &,const QString &)),
+ connection);
+ connect(socket,SIGNAL(msg_received(const QString &)),
+ SIGNAL(msg_received(const QString &)),connection);
+ connect(socket,SIGNAL(file_receive_progress(const quint64)),
+ SIGNAL(file_receive_progress(const quint64)),connection);
+ connect(socket,SIGNAL(file_saved()),SIGNAL(file_saved()),connection);
+
+ connect(socket,SIGNAL(sentData()),SIGNAL(sentData()),connection);
+ connect(socket,SIGNAL(file_header_sent()),SIGNAL(file_header_sent()),connection);
+ connect(socket,SIGNAL(sending_file_progress(const quint64)),
+ SIGNAL(sending_file_progress(const quint64)),connection);
+ connect(socket,SIGNAL(error(const QAbstractSocket::SocketError &)),
+ SLOT(getErrorStringAndEmitError(const QAbstractSocket::SocketError &)),connection);
+}
+void threadedTcpSocket::run(){
+ switch(this->mode){
+ case threadedTcpSocket::receive:
+ this->socket=new tcpSocket(this->buffersize,this);
+ this->locker->lockForRead();
+ this->connect_function(this->socket);
+ this->locker->unlock();
+ this->locker->lockForWrite();
+ this->socket->setSocketDescriptor(this->handle);
+ this->locker->unlock();
+ break;
+ case threadedTcpSocket::send:
+ this->socket=new tcpSocket(this->senderName,this->buffersize,this);
+ this->locker->lockForRead();
+ this->connect_function(this->socket);
+ this->locker->unlock();
+ break;
+ case threadedTcpSocket::send_msg:
+ this->locker->lockForWrite();
+ (*this->socket)<<this->msg;
+ this->locker->unlock();
+ break;
+ case threadedTcpSocket::send_file:
+ this->locker->lockForWrite();
+ (*this->socket)<<this->file;
+ this->locker->unlock();
+ break;
+ }
+}
+threadedTcpSocket &threadedTcpSocket::operator<<(const QString &msg){
+ this->msg=msg;
+ this->mode=threadedTcpSocket::send_msg;
+ this->start();
+return (*this);
+}
+threadedTcpSocket &threadedTcpSocket::operator<<(const QFileInfo &file){
+ this->file=file;
+ this->mode=threadedTcpSocket::send_file;
+ this->start();
+ return (*this);
}
tcpSocket::tcpSocket(quint64 buffersize, QObject *parent):QTcpSocket(parent){
emit this->sentData();
return (*this);
}
-tcpSocket &tcpSocket::operator<<(QFile &src_file){
- QFile file(src_file.fileName(),this);
+tcpSocket &tcpSocket::operator<<(const QFileInfo &src_file){
+ QtLockedFile file(src_file.fileName());
if(!this->state()!=QAbstractSocket::ConnectedState)return (*this);
this->head_data=header(this->senderName,QFileInfo(file));
QByteArray tmp_buffer;
emit this->error(QAbstractSocket::UnknownSocketError);
return (*this);
}
+ file.lock(QtLockedFile::ReadLock);
while(this->write(file.read(this->buffer_size))>0&&!this->check_canceled_then_abort()){
if(!this->flush())return (*this);
emit this->sending_file_progress(file.pos());
}
+ file.unlock();
+ file.close();
emit this->sentData();
return (*this);
}
#pragma once
#include <QtNetwork>
+#include "../file/QtLockedFile"
#include "../definition.h"
#include "../structures/header.h"
#include "../definition.h"
quint64 buffersize;
};
+ class threadedTcpSocket:virtual public QThread{
+ Q_OBJECT
+ public:
+ //This constructor is for server. it works as a session.
+ threadedTcpSocket(int,quint64 buffersize=default_bandwidth,QObject *parent=NULL);
+ //This constructor is for client. it works as a client.
+ threadedTcpSocket(const QString &senderName,const AddressAndPort &,quint64 buffersize=default_buffer_size,QObject *parent=NULL);
+ QString errorString() const;
+ threadedTcpSocket &operator<<(const QString &);
+ threadedTcpSocket &operator<<(const QFileInfo &);
+ //threadedTcpSocket &operator<<(QFile &);
+ signals:
+ QString file_pending() const;
+ QString fileStream_openFailed(const QFile::FileError &,const QString &) const;
+
+ void msg_received(const QString &) const;
+
+ void file_receive_progress(const quint64 streamPos) const;
+ void file_saved() const;
+
+ void sentData();
+ void file_header_sent();
+ void sending_file_progress(const quint64 pos);
+ void error(const QAbstractSocket::SocketError &);
+ private slots:
+ void getErrorStringAndEmitError(const QAbstractSocket::SocketError &);
+ protected:
+ void run();
+ private:
+ void connect_function(tcpSocket *socket);
+ enum Mode{receive,send,send_msg,send_file} mode;
+ tcpSocket *socket;
+ AddressAndPort to;
+ QString senderName,eStr,msg;
+ QFileInfo file;
+ QReadWriteLock *locker;
+ int handle;
+ quint64 buffersize;
+ };
+
class tcpSocket:public QTcpSocket{
Q_OBJECT
public:
structures::header header_data() const;
//Calling operator<<(QFile), the specified file stream will be copied.
tcpSocket &operator<<(const QString &),
- &operator<<(QFile &);
+ &operator<<(const QFileInfo &);
signals:
QString file_pending() const;
QString fileStream_openFailed(const QFile::FileError &,const QString &) const;
quint16 header_size,buffer_size,timeout_time;
structures::header head_data;
bool canceled;
- QString where_to_save;
- QString senderName;
+ QString where_to_save, senderName;
};
}
//Client behavior
void mainWindow::on_sendButton_clicked(){
QList<AddressAndPort> addressList=this->memberList->addressPortList();
-#ifdef _OMP
+#ifdef _OPENMP
#pragma omp parallel for
#endif
for(int index=0;index<addressList.size();index++){