ArnLib  4.0.x
Active Registry Network
ArnMonitor.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2022 Michael Wiklund.
2 // All rights reserved.
3 // Contact: arnlib@wiklunden.se
4 //
5 // This file is part of the ArnLib - Active Registry Network.
6 // Parts of ArnLib depend on Qt and/or other libraries that have their own
7 // licenses. Usage of these other libraries is subject to their respective
8 // license agreements.
9 //
10 // GNU Lesser General Public License Usage
11 // This file may be used under the terms of the GNU Lesser General Public
12 // License version 2.1 as published by the Free Software Foundation and
13 // appearing in the file LICENSE_LGPL.txt included in the packaging of this
14 // file. In addition, as a special exception, you may use the rights described
15 // in the Nokia Qt LGPL Exception version 1.1, included in the file
16 // LGPL_EXCEPTION.txt in this package.
17 //
18 // GNU General Public License Usage
19 // Alternatively, this file may be used under the terms of the GNU General Public
20 // License version 3.0 as published by the Free Software Foundation and appearing
21 // in the file LICENSE_GPL.txt included in the packaging of this file.
22 //
23 // Other Usage
24 // Alternatively, this file may be used in accordance with the terms and conditions
25 // contained in a signed written agreement between you and Michael Wiklund.
26 //
27 // This program is distributed in the hope that it will be useful, but WITHOUT ANY
28 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
29 // PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
30 //
31 
32 #include "ArnInc/ArnMonitor.hpp"
33 #include "private/ArnMonitor_p.hpp"
34 #include "ArnInc/ArnMonEvent.hpp"
35 #include "ArnInc/ArnClient.hpp"
36 #include "ArnInc/ArnLib.hpp"
37 #include "ArnInc/ArnEvent.hpp"
38 #include "ArnInc/ArnItemB.hpp"
39 #include "ArnItemNet.hpp"
40 #include "ArnSync.hpp"
41 #include "ArnLink.hpp"
42 #include <QDebug>
43 #include <QTime>
44 
45 
46 ArnMonitorPrivate::ArnMonitorPrivate()
47 {
48  _arnClient = arnNullptr;
49  _reference = arnNullptr;
50  _localMonItem = arnNullptr;
51 }
52 
53 
54 ArnMonitorPrivate::~ArnMonitorPrivate()
55 {
56 }
57 
58 
59 void ArnMonitor::init()
60 {
61 }
62 
63 
64 ArnMonitor::ArnMonitor( QObject* parent)
65  : ArnItemB( parent)
66  , d_ptr( new ArnMonitorPrivate)
67 {
68  init();
69 }
70 
71 
72 ArnMonitor::ArnMonitor(const QString& path, QObject* parent)
73  : ArnItemB( parent)
74  , d_ptr( new ArnMonitorPrivate)
75 {
76  init();
77  start( path);
78 }
79 
80 
81 ArnMonitor::ArnMonitor( ArnMonitorPrivate& dd, QObject* parent)
82  : ArnItemB( parent)
83  , d_ptr( &dd)
84 {
85  init();
86 }
87 
88 
90 {
91  Q_D(ArnMonitor);
92 
93  if (d->_localMonItem) {
94  delete d->_localMonItem;
95  }
96 
97  delete d_ptr;
98 }
99 
100 
102 {
103  Q_D(ArnMonitor);
104 
105  d->_arnClient = client;
106 }
107 
108 
109 void ArnMonitor::setClient( const QString& id)
110 {
111  Q_D(ArnMonitor);
112 
113  d->_arnClient = ArnClient::getClient( id);
114 }
115 
116 
117 QString ArnMonitor::clientId() const
118 {
119  Q_D(const ArnMonitor);
120 
121  if (!d->_arnClient) return QString();
122  return d->_arnClient->id();
123 }
124 
125 
127 {
128  Q_D(const ArnMonitor);
129 
130  return d->_arnClient;
131 }
132 
133 
134 void ArnMonitor::setMonitorPath( const QString& path, ArnClient *client)
135 {
136  Q_D(ArnMonitor);
137 
138  start( path, client ? client : d->_arnClient.data());
139 }
140 
141 
142 bool ArnMonitor::start( const QString& path, ArnClient* client)
143 {
144  Q_D(ArnMonitor);
145 
146  d->_arnClient = client;
147  d->_monitorPath = inPathConvert( Arn::fullPath( path));
148  if (!d->_monitorPath.endsWith("/")) d->_monitorPath += "/";
149 
150  if (d->_localMonItem) {
151  delete d->_localMonItem;
152  d->_localMonItem = arnNullptr;
153  }
154 
155  if (d->_arnClient) {
156  d->_arnClient.data()->getLocalRemotePath( d->_monitorPath, d->_localMountPath, d->_remoteMountPath);
157  // No recursion due to no emit of arnItemCreated as this is a folder
158  if (!open( d->_monitorPath)) return false;
159  // Force an itemNet (if not already exist), as this is a folder
160  bool isNew;
161  d->_arnClient->newNetItem( d->_monitorPath, Arn::ObjectSyncMode::Normal, &isNew);
162 
163  if (Arn::debugMonitor) qDebug() << "Monitor start: new=" << isNew << " path=" << d->_monitorPath;
164  if (isNew) {
165  if (Arn::debugMonitorTest) qDebug() << "ArnMonitor-Test: Invoke monitorStart Before";
166  QMetaObject::invokeMethod( this,
167  "sendArnMonEvent",
168  Qt::QueuedConnection, // make sure started after all setup is done in this thread
169  Q_ARG( int, ArnMonEventType::MonitorStart));
171  // QTime ts = QTime::currentTime();
172  // while (QTime::currentTime() < ts.addSecs(5));
173  if (Arn::debugMonitorTest) qDebug() << "ArnMonitor-Test: Invoke monitorStart After (delay)";
174  }
175  else {
176  if (Arn::debugMonitorTest) qDebug() << "ArnMonitor-Test: Invoke monitorReStart Before";
177  QMetaObject::invokeMethod( this,
178  "sendArnMonEvent",
179  Qt::QueuedConnection, // make sure restarted after all setup is done in this thread
180  Q_ARG( int, ArnMonEventType::MonitorReStart));
181  if (Arn::debugMonitorTest) qDebug() << "ArnMonitor-Test: Invoke monitorReStart After (delay)";
182  }
183  }
184  else { // No client, do local monitor. 2 items used, "sensor" (ArnItemNet) and this ArnMonitor to same path.
185  if (!open( d->_monitorPath)) return false;
186 
187  d->_localMonItem = new ArnItemNet( arnNullptr);
188  if (!d->_localMonItem->open( d->_monitorPath)) {
189  close();
190  return false;
191  }
192 
193  d->_localMonItem->setNetId( linkId());
194 
195  if (Arn::debugMonitor) qDebug() << "Monitor start (local-items): path="
196  << d->_monitorPath << " id=" << linkId();
197  QMetaObject::invokeMethod( this,
198  "setupLocalMonitorItem",
199  Qt::QueuedConnection // make sure called after all setup is done in this thread
200  );
201  }
202 
203  connect( this, SIGNAL(arnLinkDestroyed()), this, SIGNAL(monitorClosed()));
204  return true;
205 }
206 
207 
208 bool ArnMonitor::start( const QString& path)
209 {
210  return start( path, client());
211 }
212 
213 
214 QString ArnMonitor::monitorPath() const
215 {
216  Q_D(const ArnMonitor);
217 
218  return d->_monitorPath;
219 }
220 
221 
223 {
224  Q_D(ArnMonitor);
225 
226  d->_foundChilds.clear();
227  sendArnMonEvent( ArnMonEventType::MonitorReStart);
228 }
229 
230 
231 void ArnMonitor::setReference( void* reference)
232 {
233  Q_D(ArnMonitor);
234 
235  d->_reference = reference;
236 }
237 
238 
240 {
241  Q_D(const ArnMonitor);
242 
243  return d->_reference;
244 }
245 
246 
247 void ArnMonitor::sendArnMonEvent( int type, const QByteArray& data)
248 {
249  Q_D(ArnMonitor);
250 
251  if (!isOpen()) return;
252 
253  ArnEvMonitor ev( type, data, true, d->_arnClient);
254  sendArnEventLink( &ev);
255 }
256 
257 
258 void ArnMonitor::setupLocalMonitorItem()
259 {
260  Q_D(ArnMonitor);
261 
262  if (!d->_localMonItem) return;
263 
264  ArnSync::setupMonitorItem( d->_localMonItem);
265 }
266 
267 
268 void ArnMonitor::dispatchArnMonEvent( int type, const QByteArray& data, bool isLocal)
269 {
270  Q_D(ArnMonitor);
271 
272  if (Arn::debugMonitor && isLocal) {
273  qDebug() << "Dipatch Arn event (local): type=" << ArnMonEventType::txt().getTxt( type)
274  << " data=" << data << " monPath=" << d->_monitorPath;
275  }
276 
277  switch (type) {
279  // Fall throu
281  doEventItemFoundCreated( type, data, isLocal);
282  break;
284  doEventItemDeleted( data, isLocal);
285  break;
287  doEventItemModeChg( data, isLocal);
288  break;
290  if (!d->_arnClient && d->_localMonItem) { // Local monitor event
292  ArnSync::doChildsToEvent( d->_localMonItem);
293  }
294  break;
295  default:
296  break; // This event is not handled
297  }
298 }
299 
300 
301 void ArnMonitor::doEventItemFoundCreated( int type, const QByteArray& data, bool isLocal)
302 {
303  Q_D(ArnMonitor);
304 
305  QString foundRemotePath = QString::fromUtf8( data.constData(), data.size());
306  QString foundLocalPath = toLocalPath( foundRemotePath);
307 
309  // "created" (new fresh) is special case of "found"
310  emit arnItemCreated( outPathConvert( foundLocalPath));
311  }
312 
313  if (Arn::debugMonitor && !isLocal) {
314  qDebug() << "Dipatch Arn event: type=" << ArnMonEventType::txt().getTxt( type)
315  << " remotePath=" << foundRemotePath << " localPath=" << foundLocalPath
316  << " monPath=" << d->_monitorPath;
317  }
318 
319  QString childPath = Arn::childPath( d->_monitorPath, foundLocalPath);
320  // qDebug() << "### arnMon dispArnEv: childPath=" << childPath;
321  if (!childPath.isEmpty()) { // Should always be none emty ...
322  if (!d->_foundChilds.contains( childPath)) { // Only send events about unknown items
323  d->_foundChilds += childPath;
324  // qDebug() << "### arnMon dispArnEv: Emit chFound childPath=" << childPath;
325  emit arnChildFound( outPathConvert( childPath));
326  if (childPath.endsWith('/')) emit arnChildFoundFolder( outPathConvert( childPath));
327  else emit arnChildFoundLeaf( outPathConvert( childPath));
328  }
329  }
330 }
331 
332 
333 void ArnMonitor::doEventItemDeleted( const QByteArray& data, bool isLocal)
334 {
335  Q_D(ArnMonitor);
336 
337  QString delRemotePath = QString::fromUtf8( data.constData(), data.size());
338  QString delLocalPath = toLocalPath( delRemotePath);
339 
340  if (Arn::debugMonitor && !isLocal) {
341  qDebug() << "Deleted Arn event: remotePath=" << delRemotePath
342  << " localPath=" << delLocalPath << " monPath=" << d->_monitorPath;
343  }
344 
345  QString childPath = Arn::childPath( d->_monitorPath, delLocalPath);
346  if (childPath == delLocalPath) { // A child has been deleted
347  foundChildDeleted( delLocalPath);
348  emit arnChildDeleted( childPath);
349  }
350  emit arnItemDeleted( delLocalPath);
351 }
352 
353 
354 void ArnMonitor::doEventItemModeChg( const QByteArray& data, bool isLocal)
355 {
356  Q_D(ArnMonitor);
357 
358  Arn::XStringMap xsm( data);
359  QString itemRemotePath = xsm.valueString("path");
360  QString itemLocalPath = toLocalPath( itemRemotePath);
361  Arn::ObjectMode mode = ArnItemNet::stringToObjectMode( xsm.value("mode"));
362 
363  if (Arn::debugMonitor && !isLocal) {
364  qDebug() << "ModeChg Arn event: remotePath=" << itemRemotePath
365  << " localPath=" << itemLocalPath << "mode=" << mode.toString()
366  << " monPath=" << d->_monitorPath;
367  }
368 
369  QString childPath = Arn::childPath( d->_monitorPath, itemLocalPath);
370  if (childPath == itemLocalPath) { // A child has been deleted
371  emit arnChildModeChanged( childPath, mode);
372  }
373  emit arnItemModeChanged( itemLocalPath, mode);
374 }
375 
376 
377 void ArnMonitor::foundChildDeleted( const QString& path)
378 {
379  Q_D(ArnMonitor);
380 
381  int i = d->_foundChilds.indexOf( inPathConvert( path));
382  // qDebug() << "### arnMon foundChDel: path=" << path << " i=" << i;
383  if (i >= 0) {
384  d->_foundChilds.removeAt(i);
385  }
386 }
387 
388 
389 QString ArnMonitor::outPathConvert( const QString& path)
390 {
391  return path; // No conversion as standard
392 }
393 
394 
395 QString ArnMonitor::inPathConvert( const QString& path)
396 {
397  return path; // No conversion as standard
398 }
399 
400 
401 void ArnMonitor::customEvent( QEvent* ev)
402 {
403  Q_D(ArnMonitor);
404 
405  int evIdx = ev->type() - ArnEvent::baseType();
406  switch (evIdx) {
408  {
409  ArnEvMonitor* e = static_cast<ArnEvMonitor*>( ev);
410  ArnBasicItem* target = static_cast<ArnBasicItem*>( e->target());
411  if (!target) break; // No target, deleted/closed ...
412 
413  // qDebug() << "ArnMonitor Ev Monitor:";
414  if (e->sessionHandler() == d->_arnClient) // Event is for this session (client)
415  dispatchArnMonEvent( e->monEvType(), e->data(), e->isLocal());
416  break;
417  }
419  {
420  ArnEvRetired* e = static_cast<ArnEvRetired*>( ev);
421  ArnBasicItem* target = static_cast<ArnBasicItem*>( e->target());
422  if (!target) break; // No target, deleted/closed ...
423 
424  QString destroyPath = e->isBelow() ? e->startLink()->linkPath() : target->path();
425  // qDebug() << "ArnMonitor Ev Retired: path=" << destroyPath << " inPath=" << target->path();
426  dispatchArnMonEvent( ArnMonEventType::ItemDeleted, destroyPath.toUtf8(), true);
427  break;
428  }
429  default:
430  break;
431  }
432 
433  ArnItemB::customEvent( ev);
434 }
435 
436 
437 QString ArnMonitor::toLocalPath( const QString& remotePath) const
438 {
439  Q_D(const ArnMonitor);
440 
441  return Arn::changeBasePath( d->_remoteMountPath, d->_localMountPath, remotePath);
442 }
QString childPath(const QString &parentPath, const QString &posterityPath)
Get substring for child from a path (posterityPath)
Definition: Arn.cpp:100
static int baseType(int setVal=-1)
Definition: ArnEvent.cpp:62
void reStart()
The monitor is restarted.
Definition: ArnMonitor.cpp:222
const QByteArray & data() const
Definition: ArnEvent.hpp:188
Newly created Arn object.
Definition: ArnMonEvent.hpp:47
void close()
Close the handle.
void foundChildDeleted(const QString &path)
Help telling the monitor about deletion of a previous found child.
Definition: ArnMonitor.cpp:377
Container class with string representation for serialized data.
Definition: XStringMap.hpp:107
void arnChildFoundFolder(const QString &path)
Signal emitted for present and newly created folder childs in the monitor folder. ...
void setMonitorPath(const QString &path, ArnClient *client=arnNullptr)
Set the path to be monitored.
Definition: ArnMonitor.cpp:134
void arnChildFoundLeaf(const QString &path)
Signal emitted for present and newly created leaf childs in the monitor folder.
void setClient(ArnClient *client)
Set the client to be used.
Definition: ArnMonitor.cpp:101
QString fullPath(const QString &path)
Convert a path to a full absolute path.
Definition: Arn.cpp:82
An Arn object changed mode.
Definition: ArnMonEvent.hpp:53
void arnChildModeChanged(const QString &path, int mode)
Signal emitted for mode changing childs in the monitor folder.
void * reference() const
Get the stored external reference.
Definition: ArnMonitor.cpp:239
void setReference(void *reference)
Set an associated external reference.
Definition: ArnMonitor.cpp:231
QString monitorPath() const
Get the monitored path
Definition: ArnMonitor.cpp:214
bool start(const QString &path, ArnClient *client)
Starts the monitoring.
Definition: ArnMonitor.cpp:142
ArnClient * client() const
Get the used client
Definition: ArnMonitor.cpp:126
QString changeBasePath(const QString &oldBasePath, const QString &newBasePath, const QString &path)
Change the base (start) of a path.
Definition: Arn.cpp:114
An Arn object was deleted.
Definition: ArnMonEvent.hpp:51
bool open(const QString &path)
Open a handle to an Arn Data Object
Definition: ArnItemB.cpp:91
Class for connecting to an Arn Server.
Definition: ArnClient.hpp:104
ArnLink * startLink() const
Definition: ArnEvent.hpp:210
void arnChildFound(const QString &path)
Signal emitted for present and newly created childs in the monitor folder.
void * sessionHandler() const
Definition: ArnEvent.hpp:194
ArnMonitor(QObject *parent=arnNullptr)
Definition: ArnMonitor.cpp:64
bool isOpen() const
State of the handle.
QString path(Arn::NameF nameF=Arn::NameF::EmptyOk) const
Path of the Arn Data Object
Arn::DataType type() const
The type stored in the Arn Data Object
int monEvType() const
Definition: ArnEvent.hpp:185
bool isBelow() const
Definition: ArnEvent.hpp:213
void arnItemDeleted(const QString &path)
Signal emitted when an Arn Data Object is deleted in the tree below.
Base class handle for an Arn Data Object.
Definition: ArnItemB.hpp:59
void monitorClosed()
Signal emitted when the Arn Monitor is closed down.
void arnItemModeChanged(const QString &path, int mode)
Signal emitted when an Arn Data Object changes mode in the tree below.
uint linkId() const
Get the id for this Arn Data Object
Internal: start the Monitor.
Definition: ArnMonEvent.hpp:56
void arnChildDeleted(const QString &path)
Signal emitted for deleted childs in the monitor folder.
Internal: restart the Monitor.
Definition: ArnMonEvent.hpp:58
Found a present Arn object.
Definition: ArnMonEvent.hpp:49
bool debugMonitor
Definition: ArnLib.cpp:43
bool debugMonitorTest
Definition: ArnLib.cpp:44
void arnLinkDestroyed()
Signal emitted when the Arn Data Object is destroyed.
A client remote monitor to detect changes at server.
Definition: ArnMonitor.hpp:65
void * target() const
Definition: ArnEvent.hpp:116
bool isLocal() const
Definition: ArnEvent.hpp:191
static ArnClient * getClient(const QString &id)
Get a client by its id.
Definition: ArnClient.cpp:492
void arnItemCreated(const QString &path)
Signal emitted when an Arn Data Object is created in the tree below.
QString clientId() const
Get the id name of the used client
Definition: ArnMonitor.cpp:117
Base class handle for an Arn Data Object.