|
|
@@ -1,73 +1,132 @@
|
|
|
#include "vsingleinstanceguard.h"
|
|
|
#include <QDebug>
|
|
|
|
|
|
-const QString VSingleInstanceGuard::m_memKey = "vnote_shared_memory";
|
|
|
-const QString VSingleInstanceGuard::m_semKey = "vnote_semaphore";
|
|
|
-const int VSingleInstanceGuard::m_magic = 133191933;
|
|
|
+#include "utils/vutils.h"
|
|
|
+
|
|
|
+const QString VSingleInstanceGuard::c_memKey = "vnote_shared_memory";
|
|
|
+const int VSingleInstanceGuard::c_magic = 133191933;
|
|
|
|
|
|
VSingleInstanceGuard::VSingleInstanceGuard()
|
|
|
- : m_sharedMemory(m_memKey), m_sem(m_semKey, 1)
|
|
|
+ : m_sharedMemory(c_memKey)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-VSingleInstanceGuard::~VSingleInstanceGuard()
|
|
|
+bool VSingleInstanceGuard::tryRun()
|
|
|
{
|
|
|
- if (m_sharedMemory.isAttached()) {
|
|
|
- detachMemory();
|
|
|
+ // If we can attach to the sharedmemory, there is another instance running.
|
|
|
+ // In Linux, crashes may cause the shared memory segment remains. In this case,
|
|
|
+ // this will attach to the old segment, then exit, freeing the old segment.
|
|
|
+ if (m_sharedMemory.attach()) {
|
|
|
+ qDebug() << "another instance is running";
|
|
|
+ return false;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-void VSingleInstanceGuard::detachMemory()
|
|
|
-{
|
|
|
- m_sem.acquire();
|
|
|
- m_sharedMemory.detach();
|
|
|
- m_sem.release();
|
|
|
-}
|
|
|
-
|
|
|
-bool VSingleInstanceGuard::tryAttach()
|
|
|
-{
|
|
|
- m_sem.acquire();
|
|
|
- bool ret = m_sharedMemory.attach();
|
|
|
- m_sem.release();
|
|
|
+ // Try to create it.
|
|
|
+ bool ret = m_sharedMemory.create(sizeof(SharedStruct));
|
|
|
if (ret) {
|
|
|
+ // We created it.
|
|
|
m_sharedMemory.lock();
|
|
|
SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
|
|
|
- str->m_activeRequest = 1;
|
|
|
+ str->m_magic = c_magic;
|
|
|
+ str->m_filesBufIdx = 0;
|
|
|
m_sharedMemory.unlock();
|
|
|
- detachMemory();
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ qDebug() << "fail to create shared memory segment";
|
|
|
+ return false;
|
|
|
}
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
-bool VSingleInstanceGuard::tryRun()
|
|
|
+void VSingleInstanceGuard::openExternalFiles(const QStringList &p_files)
|
|
|
{
|
|
|
- // If we can attach to the sharedmemory, there is another instance running.
|
|
|
- if (tryAttach()) {
|
|
|
- qDebug() << "another instance is running";
|
|
|
- return false;
|
|
|
+ if (p_files.isEmpty()) {
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- // Try to create it
|
|
|
- m_sem.acquire();
|
|
|
- bool ret = m_sharedMemory.create(sizeof(SharedStruct));
|
|
|
- m_sem.release();
|
|
|
- if (ret) {
|
|
|
- // We created it
|
|
|
+ if (!m_sharedMemory.isAttached()) {
|
|
|
+ if (!m_sharedMemory.attach()) {
|
|
|
+ qDebug() << "fail to attach to the shared memory segment"
|
|
|
+ << (m_sharedMemory.error() ? m_sharedMemory.errorString() : "");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ qDebug() << "try to request another instance to open files" << p_files;
|
|
|
+
|
|
|
+ int idx = 0;
|
|
|
+ int tryCount = 100;
|
|
|
+ while (tryCount--) {
|
|
|
+ qDebug() << "set shared memory one round" << idx << "of" << p_files.size();
|
|
|
m_sharedMemory.lock();
|
|
|
SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
|
|
|
- str->m_magic = m_magic;
|
|
|
- str->m_activeRequest = 0;
|
|
|
+ V_ASSERT(str->m_magic == c_magic);
|
|
|
+ for (; idx < p_files.size(); ++idx) {
|
|
|
+ if (p_files[idx].size() + 1 > FilesBufCount) {
|
|
|
+ qDebug() << "skip file since its long name" << p_files[idx];
|
|
|
+ // Skip this long long name file.
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!appendFileToBuffer(str, p_files[idx])) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
m_sharedMemory.unlock();
|
|
|
- return true;
|
|
|
- } else {
|
|
|
- // Maybe another thread create it
|
|
|
- if (tryAttach()) {
|
|
|
- qDebug() << "another instance is running";
|
|
|
- return false;
|
|
|
+
|
|
|
+ if (idx < p_files.size()) {
|
|
|
+ VUtils::sleepWait(500);
|
|
|
} else {
|
|
|
- // Something wrong here
|
|
|
- qWarning() << "fail to create or attach shared memory segment";
|
|
|
- return false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool VSingleInstanceGuard::appendFileToBuffer(SharedStruct *p_str, const QString &p_file)
|
|
|
+{
|
|
|
+ if (p_file.isEmpty()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ int strSize = p_file.size();
|
|
|
+ if (strSize + 1 > FilesBufCount - p_str->m_filesBufIdx) {
|
|
|
+ qDebug() << "no enough space for" << p_file;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Put the size first.
|
|
|
+ p_str->m_filesBuf[p_str->m_filesBufIdx++] = (ushort)strSize;
|
|
|
+ const QChar *data = p_file.constData();
|
|
|
+ for (int i = 0; i < strSize; ++i) {
|
|
|
+ p_str->m_filesBuf[p_str->m_filesBufIdx++] = data[i].unicode();
|
|
|
+ }
|
|
|
+
|
|
|
+ qDebug() << "after appended one file" << p_str->m_filesBufIdx << p_file;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+QStringList VSingleInstanceGuard::fetchFilesToOpen()
|
|
|
+{
|
|
|
+ QStringList files;
|
|
|
+ Q_ASSERT(m_sharedMemory.isAttached());
|
|
|
+ m_sharedMemory.lock();
|
|
|
+ SharedStruct *str = (SharedStruct *)m_sharedMemory.data();
|
|
|
+ Q_ASSERT(str->m_magic == c_magic);
|
|
|
+ Q_ASSERT(str->m_filesBufIdx <= FilesBufCount);
|
|
|
+ int idx = 0;
|
|
|
+ while (idx < str->m_filesBufIdx) {
|
|
|
+ int strSize = str->m_filesBuf[idx++];
|
|
|
+ Q_ASSERT(strSize <= str->m_filesBufIdx - idx);
|
|
|
+ QString file;
|
|
|
+ for (int i = 0; i < strSize; ++i) {
|
|
|
+ file.append(QChar(str->m_filesBuf[idx++]));
|
|
|
}
|
|
|
+
|
|
|
+ files.append(file);
|
|
|
}
|
|
|
+
|
|
|
+ str->m_filesBufIdx = 0;
|
|
|
+ m_sharedMemory.unlock();
|
|
|
+
|
|
|
+ return files;
|
|
|
}
|