Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,31 @@
SET(xdr_dh_SRCS
XDR_DirHandler.cpp
XDR_DirHandler_ifc.cpp
)
SET(xdr_dh_HDRS
XDR_DirHandler.h
XDR_DirHandler_ifc.h
)
IF(WIN32)
LIST(APPEND xdr_dh_SRCS
XDR_DirHandler_win.cpp
)
LIST(APPEND xdr_dh_HDRS
XDR_DirHandler_win.h
)
ELSE(WIN32)
LIST(APPEND xdr_dh_SRCS
XDR_DirHandler_linux.cpp
)
LIST(APPEND xdr_dh_HDRS
XDR_DirHandler_linux.h
)
ENDIF(WIN32)
NGL_ADD_LIBRARY(AAR SV xdr_qthandler_dir SHARED ${xdr_dh_SRCS} ${xdr_dh_HDRS})
NGL_TARGET_LINK_LIBRARIES(xdr_qthandler_dir
PRIVATE
NGLLogger
PUBLIC
Qt5::Core
)
NGL_INSTALL_TARGET(xdr_qthandler_dir)
@@ -0,0 +1,58 @@
/**
* Scan directory for new XDR files
* $Id$
* $HeadURL$
* $Author$
*/
#include "XDR_DirHandler.h"
#include <QtCore/QTimer>
#include <QtCore/QThread>
#ifdef WIN32
#include "XDR_DirHandler_win.h"
#else
#include "XDR_DirHandler_linux.h"
#endif
XDR_DirHandler::XDR_DirHandler(const QString &dirToWatch, bool startWatching, QObject *parent)
: QObject(parent)
, m_workerThread(new QThread)
, m_workerObject(nullptr)
, m_startWatching(startWatching)
, m_dirToWatch(dirToWatch)
{
#ifdef WIN32
m_workerObject = new XDR_DirHandlerWin(dirToWatch);
#else
m_workerObject = new XDR_DirHandlerLinux(dirToWatch);
#endif
m_workerThread->start();
m_workerObject->moveToThread(m_workerThread);
connect(m_workerObject, &XDR_DirHandlerIfc::newTelegramArrived,
this, &XDR_DirHandler::newTelegramArrived);
connect(m_workerThread, &QThread::finished,
m_workerObject, &XDR_DirHandlerIfc::deleteLater);
if (startWatching)
QTimer::singleShot(0, m_workerObject, &XDR_DirHandlerIfc::startWatching);
}
XDR_DirHandler::~XDR_DirHandler()
{
m_workerThread->requestInterruption();
m_workerThread->quit();
if (!m_workerThread->wait(10000))
m_workerThread->terminate();
delete m_workerThread;
}
void XDR_DirHandler::startWatching()
{
if (!m_startWatching)
{
QTimer::singleShot(0, m_workerObject, &XDR_DirHandlerIfc::startWatching);
m_startWatching = true;
}
}
@@ -0,0 +1,62 @@
/**
* Scan directory for new XDR files
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QtCore/QObject>
#include <QtCore/QString>
#ifndef XDR_QTHANDLER_DIR_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define XDR_QTHANDLER_DIR_EXPORT
# else
# ifdef MAKE_XDR_QTHANDLER_DIR_LIB
# define XDR_QTHANDLER_DIR_EXPORT Q_DECL_EXPORT
# else
# define XDR_QTHANDLER_DIR_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
class XDR_DirHandlerIfc;
class XDR_QTHANDLER_DIR_EXPORT XDR_DirHandler : public QObject
{
Q_OBJECT
public:
XDR_DirHandler(const QString &dirToWatch, bool startWatching = true, QObject *parent = nullptr);
~XDR_DirHandler();
void startWatching();
QString dirToWatch() const { return m_dirToWatch; }
protected Q_SLOTS:
virtual void newTelegramArrived(const QString &fullPath) = 0;
private:
QThread *m_workerThread;
XDR_DirHandlerIfc *m_workerObject;
bool m_startWatching;
QString m_dirToWatch;
};
class XDR_QTHANDLER_DIR_EXPORT XDR_DirHandler_emit : public XDR_DirHandler
{
Q_OBJECT
public:
XDR_DirHandler_emit(const QString &dirToWatch, QObject *parent = nullptr)
: XDR_DirHandler(dirToWatch, true, parent)
{}
~XDR_DirHandler_emit()
{}
protected:
virtual void newTelegramArrived(const QString &fullPath)
{
emit newTelegram(fullPath);
}
Q_SIGNALS:
void newTelegram(const QString &fullPath);
};
@@ -0,0 +1,19 @@
/**
* Scan directory for new XDR files - internal interfacefor OS abstraction
* $Id$
* $HeadURL$
* $Author$
*/
#include "XDR_DirHandler_ifc.h"
XDR_DirHandlerIfc::XDR_DirHandlerIfc(const QString &dirToWatch, QObject *parent)
: QObject(parent)
, mDirToWatchBA(dirToWatch.toLocal8Bit())
, mDirToWatch(dirToWatch)
{
if (!mDirToWatch.endsWith(QLatin1Char('/')))
mDirToWatch += QLatin1Char('/');
if (!mDirToWatchBA.endsWith('/'))
mDirToWatchBA += '/';
}
@@ -0,0 +1,27 @@
/**
* Scan directory for new XDR files - internal interfacefor OS abstraction
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QObject>
#include <QByteArray>
#include <QString>
class XDR_DirHandlerIfc : public QObject
{
Q_OBJECT
public:
XDR_DirHandlerIfc(const QString &dirToWatch, QObject *parent = nullptr);
public Q_SLOTS:
virtual void startWatching() = 0;
Q_SIGNALS:
void newTelegramArrived(const QString &fullPath);
protected:
QByteArray mDirToWatchBA;
QString mDirToWatch;
};
@@ -0,0 +1,199 @@
/**
* Scan directory for new XDR files - windows specific implementation
* $Id$
* $HeadURL$
* $Author$
*/
#include "XDR_DirHandler_linux.h"
#include <QMap>
#include <QThread>
#include <QTimer>
#include <QVarLengthArray>
#include <poll.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
void XDR_DirHandlerLinux::startWatching()
{
onScanDirectory();
startEPoll();
}
void XDR_DirHandlerLinux::onScanDirectory()
{
QByteArray nameBA;
nameBA.reserve(128);
QVarLengthArray<char, 512> tmpFilename;
const int tmpFilenameOffset = mDirToWatchBA.size();
tmpFilename.clear();
tmpFilename.append(mDirToWatchBA.data(), mDirToWatchBA.size());
// Verzeichnis oeffnen
DIR *dirp = opendir(mDirToWatchBA.constData());
if(!dirp)
return;
// Schleife ueber alle Files
dirent* entry;
while ((entry = readdir(dirp)) != nullptr) {
const char *name = entry->d_name;
// skip directories
size_t len = strlen(name);
// skip "."
if( len == 1 && name[0] == '.' )
continue;
// skip ".."
if( len == 2 && name[0] == '.' && name[1] == '.' )
continue;
if(len > 4) {
size_t pos = len - 4;
if( name[pos] == '.' &&
tolower(name[pos+1]) == 't' &&
tolower(name[pos+2]) == 'm' &&
tolower(name[pos+3]) == 'p')
continue;
}
// ist es ein Verzeichnis?
struct stat st;
tmpFilename.resize(tmpFilenameOffset);
tmpFilename.append(name, len);
tmpFilename.append('\0');
int res = stat(tmpFilename.constData(), &st);
if (res || S_ISDIR(st.st_mode) ) {
// Unterverzeichnis
continue;
}
// einfuegen
nameBA.clear();
nameBA.append(name, len);
m_newFilesMap.insert(nameBA, 1);
}
closedir(dirp);
// map is sorted by key, we don't care about value
QMap<QByteArray, int>::ConstIterator it = m_newFilesMap.constBegin();
QMap<QByteArray, int>::ConstIterator end = m_newFilesMap.constEnd();
for( ; it != end; ++it)
{
emit newTelegramArrived(mDirToWatch + QString::fromLocal8Bit(it.key()));
}
QTimer::singleShot(5000, this, &XDR_DirHandlerLinux::clearNewFilesMap);
}
void XDR_DirHandlerLinux::clearNewFilesMap()
{
m_newFilesMap.clear();
}
#if 0
// fuer debug-Zwecke
static void /* Display information from inotify_event structure */
displayInotifyEvent(const inotify_event *i)
{
printf(" wd =%2d; ", i->wd);
if (i->cookie > 0)
printf("cookie =%4d; ", i->cookie);
printf("mask = ");
if (i->mask & IN_ACCESS) printf("IN_ACCESS ");
if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");
if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");
if (i->mask & IN_CREATE) printf("IN_CREATE ");
if (i->mask & IN_DELETE) printf("IN_DELETE ");
if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");
if (i->mask & IN_IGNORED) printf("IN_IGNORED ");
if (i->mask & IN_ISDIR) printf("IN_ISDIR ");
if (i->mask & IN_MODIFY) printf("IN_MODIFY ");
if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");
if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");
if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");
if (i->mask & IN_OPEN) printf("IN_OPEN ");
if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");
if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");
printf("\n");
if (i->len > 0)
printf(" name = %s\n", i->name);
}
#endif
void XDR_DirHandlerLinux::startEPoll()
{
int inotifyFd = inotify_init();
if (inotifyFd != -1) {
// Entweder wenn foo.tmp nach foo verschoben wird oder
// wenn eine Datei geschlossen wird (inklusive Schreibvorgang vorher)
// d.h. wir würden das umbenennen von foo.tmp nach foo gar nicht mehr benoetigen
int wd = inotify_add_watch(inotifyFd, mDirToWatchBA.constData(), IN_MOVED_TO|IN_CLOSE_WRITE);
if (wd != -1) {
Q_FOREVER {
if (QThread::currentThread()->isInterruptionRequested())
break;
struct pollfd fds[1];
memset(fds, 0, sizeof(fds));
fds[0].fd = inotifyFd;
fds[0].events = POLLIN | POLLPRI;
constexpr int timeout_msecs = 5;
int ret = poll(fds, 1, timeout_msecs);
if (ret > 0) {
static const int BUF_LEN = (10 * (sizeof(struct inotify_event) + NAME_MAX + 1));
char buf[BUF_LEN] __attribute__ ((aligned(8)));
int numRead = read(inotifyFd, buf, BUF_LEN);
if(numRead <= 0)
break;
for (const char *p = buf; p < buf + numRead; ) {
const inotify_event *event = reinterpret_cast<const inotify_event *>(p);
//displayInotifyEvent(event);
handleInotifyEvents(event);
p += sizeof(struct inotify_event) + event->len;
}
}
}
close(wd);
}
close(inotifyFd);
}
}
void XDR_DirHandlerLinux::handleInotifyEvents(const inotify_event *entry)
{
// wir gehen davon aus, dass wir nur IN_CLOSE_WRITE und IN_MOVED_TO
// bekommen so wie wir es auch aboniert haben.
// skip directories
if((entry->mask & IN_ISDIR) == IN_ISDIR)
return;
const char *name = entry->name;
const size_t len = strlen(name); // entry->len contains the length including \0 and padding bytes!
if (len > 4) {
size_t pos = len - 4;
if( name[pos] == '.' &&
tolower(name[pos+1]) == 't' &&
tolower(name[pos+2]) == 'm' &&
tolower(name[pos+3]) == 'p') {
return;
}
}
if (!m_newFilesMap.isEmpty()) {
if (m_newFilesMap.contains(QByteArray::fromRawData(name, len)))
return;
}
emit newTelegramArrived(mDirToWatch + QString::fromLocal8Bit(name));
}
@@ -0,0 +1,29 @@
/**
* Scan directory for new XDR files - windows specific implementation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "XDR_DirHandler_ifc.h"
#include <QMap>
struct inotify_event;
class XDR_DirHandlerLinux final : public XDR_DirHandlerIfc
{
Q_OBJECT
public:
using XDR_DirHandlerIfc::XDR_DirHandlerIfc;
private Q_SLOTS:
void onScanDirectory();
void startWatching();
void startEPoll();
void clearNewFilesMap();
private:
void handleInotifyEvents(const inotify_event *entry);
private:
QMap<QByteArray, int> m_newFilesMap; // fuer initiales lesen
};
@@ -0,0 +1,78 @@
/**
* Scan directory for new XDR files - windows specific implementation
* $Id$
* $HeadURL$
* $Author$
*/
#include "XDR_DirHandler_win.h"
#include <QtCore/QTimer>
#include <QtCore/QMap>
#include <QtCore/QVarLengthArray>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
#include <tchar.h>
void XDR_DirHandlerWin::startWatching()
{
onScanDirectory();
}
void XDR_DirHandlerWin::onScanDirectory()
{
QString lastFilename = mLastFilename;
QMap<QString, int> newFilesMap;
// Verzeichnis oeffnen
WIN32_FIND_DATA findData;
HANDLE dirp = FindFirstFile(reinterpret_cast<LPCWSTR>(mDirToWatch.utf16()), &findData);
while(dirp != INVALID_HANDLE_VALUE)
return;
// Schleife ueber alle Files
do {
// skip directories
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
{
if (FindNextFile(dirp, &findData) == 0)
break;
continue;
}
const TCHAR *name = findData.cFileName;
const size_t len = wcslen(name);
if(len > 4) {
size_t pos = len - 4;
if( name[pos] == '.' &&
_totlower(name[pos+1]) == 't' &&
_totlower(name[pos+2]) == 'm' &&
_totlower(name[pos+3]) == 'p')
continue;
}
// hatten wir schon ?
const QString nameStr = QString::fromUtf16(reinterpret_cast<const ushort*>(name), len);
if ( mLastFilename.size() && nameStr <= mLastFilename )
continue;
if (nameStr > lastFilename)
lastFilename = nameStr;
// einfuegen
newFilesMap.insert(nameStr, 1);
} while (FindNextFile(dirp, &findData) != 0);
FindClose(dirp);
mLastFilename = lastFilename;
// map is sorted by key, we don't care about value
QMap<QString, int>::ConstIterator it = newFilesMap.constBegin();
QMap<QString, int>::ConstIterator end = newFilesMap.constEnd();
for( ; it != end; ++it)
emit newTelegramArrived(mDirToWatch + it.key());
// Alle 200 msec lesen
QTimer::singleShot(200, this, &XDR_DirHandlerWin::onScanDirectory);
}
@@ -0,0 +1,23 @@
/**
* Scan directory for new XDR files - windows specific implementation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "XDR_DirHandler_ifc.h"
class XDR_DirHandlerWin : public XDR_DirHandlerIfc
{
Q_OBJECT
public:
using XDR_DirHandlerIfc::XDR_DirHandlerIfc;
private Q_SLOTS:
void onScanDirectory();
void startWatching();
private:
QString mLastFilename;
};
@@ -0,0 +1,21 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QtCore/qglobal.h>
#ifndef XDR_QTHANDLER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define XDR_QTHANDLER_EXPORT
# else
# if defined(MAKE_XDR_QTHANDLER_LIB)
# define XDR_QTHANDLER_EXPORT Q_DECL_EXPORT
# else
# define XDR_QTHANDLER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif