Remoto - VFS: VFS_node Class Reference
Remoto - VFS

VFS_node is the base class from which all other VFS_node classes derive. More...

#include <VFS_node.h>

Inheritance diagram for VFS_node:
VFS VFS_QRC VFS_acl VFS_application VFS_auth VFS_cron VFS_curl VFS_datastore VFS_ephemeral VFS_iframe VFS_logger VFS_pulse VFS_session VFS_sessionManager VFS_sessionTokenPruner VFS_stream VFS_tcp_client VFS_tcp_server VFS_thread VFS_threadpool VFS_udp_socket VFS_websocket_client VFS_websocket_server

Public Slots

virtual void applyDiff (VFS_request *r)
 Apply a diff received via subscription. More...
 
virtual void executeRequest (VFS_request *t)
 Based on the VFS_request::requestType, execute the function associated with an operation. More...
 
void notifySubscribers (VFS_node *origin, VFS_request *t)
 Propagate a diff to subscribers. More...
 
virtual void receiveResponse (VFS_request *t)
 Once a VFS_request has been completed, a response will be issued back to its _origin. More...
 
void remove (bool andDelete)
 Remove a child node. More...
 
virtual void remove (VFS_node *node=nullptr, QString *name=nullptr, QString user="server")
 Remove a child node from this node. More...
 
virtual void subtreeRequest (VFS_request *t)
 find() the target of a VFS_request, and execute the request More...
 
virtual void unsubscribeAll (VFS_node *n)
 Remove all references to a subscriber from this node. More...
 

Signals

void diff (VFS_node *origin, VFS_request *t)
 Emit a diff, which will trigger notifySubscribers() for a mounted node. More...
 
void finished (bool andDelete=false)
 Emitted if a thread fails to create its node, or a node is rm()'d, or any other reason a node has completed its lifecycle. It is deleted if andDelete==true. More...
 
void mounted ()
 Emitted when a node is mount()ed. More...
 
void unmounted (VFS_node *self)
 Emitted when a node is unmount()ed. More...
 

Public Member Functions

Q_INVOKABLE VFS_node ()
 The VFS_node constructor will add its instance to the VFS_node::__allNodes global node registry, observing thread safety rules. More...
 
virtual ~VFS_node ()
 VFS_node destructor. More...
 
virtual VFS_nodeappend (QString name, VFS_node *node, bool containerCheck=true, QString user="server")
 Append a VFS_node as a child of this node. More...
 
QString className ()
 Return the class name of a node. More...
 
virtual VFS_requestcreateRequest (VFS_request::requestType type, QString path, QString user="unknown", QJsonDocument data=QJsonDocument(), QJsonObject metadata=QJsonObject(), bool dontDelete=false)
 Create a new VFS_request with this object as _origin. More...
 
VFS_nodefind (QString path)
 Find a node by string path. More...
 
virtual VFS_nodefind (VFS_request *r)
 Find a node using a VFS_request. More...
 
VFS_nodefindChildWithName (QString name)
 Check if a child with a given name exists. More...
 
virtual bool isContainer ()
 A VFS_node may have children. More...
 
virtual VFS_nodemount ()
 Mount this node. More...
 
virtual QString reportDetails ()
 Additional details for a generated report. More...
 
QString uniqueChildName (QString name)
 Generate a unique child name. More...
 
virtual VFS_nodeunmount ()
 Unmount this node. More...
 
virtual bool validChildName (QString name)
 Check if a node name is valid. More...
 

Static Public Member Functions

static bool __isNode (VFS_node *)
 Check to see if a node is in the global registry. More...
 
static QString code (QString nodename, QString libname, QString &error)
 Fetch code or any other resource from a node. More...
 

Protected Member Functions

virtual void aclDefaults (VFS_request *r)
 Return default values and features associated wth this node. More...
 
void addACLDefault (QJsonObject &acl, bool value, QString description="")
 Add a default value to the acl object. More...
 
void addACLFeature (QJsonObject &acl, QString feature, bool value, QString description="")
 Add a feature to the acl object. More...
 
void addACLFeatureGroup (QJsonObject &acl, QString feature, QString group, bool value)
 Add a feature group to the acl object. More...
 
void addACLFeatureUser (QJsonObject &acl, QString feature, QString user, bool value)
 Add a feature user to the acl object. More...
 
void addACLGroup (QJsonObject &acl, QString group, bool value)
 Add a group to the acl object. More...
 
void addACLUser (QJsonObject &acl, QString user, bool value)
 Add a user to the acl object. More...
 
virtual QByteArray icon ()
 Fetch the icon for a node. More...
 
virtual void issueRequest (VFS_node *target, VFS_request *t)
 Issue a VFS_request to its target. More...
 
virtual void issueRequest (VFS_request *t)
 A convenience function. More...
 
virtual void issueResponse (VFS_request *t)
 Once a request has been completed, issue a response. More...
 
virtual void ls (VFS_request *r)
 List the contents of this node. More...
 
virtual void metadata (VFS_request *r)
 Fetch the metadata of this node. More...
 
virtual void read (VFS_request *r)
 Return the data contents of this node, or if it's a container call ls() More...
 
virtual void releaseLock (VFS_request *r)
 Release a lock on this node. More...
 
virtual void report (VFS_request *r)
 Report debugging information about the current state of this node. More...
 
virtual void requestLock (VFS_request *r)
 Request a lock on this node. More...
 
virtual void rm (VFS_request *r)
 Remove a child entry from a node, or the node itself. More...
 
virtual void submit (VFS_request *r)
 Submit a diff to a node. More...
 
virtual void subscribe (VFS_request *r)
 Add an entry to this node's _subscription list. More...
 
virtual void unsubscribe (VFS_request *r)
 Remove an entry from this node's _subscription list. More...
 
virtual void unsubscribePath (QString path)
 Unsubscribe all references to a subpath. More...
 
virtual void write (VFS_request *r)
 Write data to this node. More...
 

Protected Attributes

VFS_children _children
 This node's children. More...
 
QMutex _lock
 A recursive mutex that is local to this node. More...
 
VFS_subscriptionType _subscribers
 This node's subscribers. These subscribers will receive diff notifications. More...
 

Static Private Member Functions

static void __addNode (VFS_node *)
 Add a node to the global registry. More...
 
static bool __removeNode (VFS_node *)
 Remove a node from the global registry. More...
 

Static Private Attributes

static QSet< VFS_node * > __allNodes
 The static global registry for all exiting nodes, used for thread safety checks. More...
 
static QMutex __allNodesMutex
 The global registry mutex, which will lock when node creation or deletion is being performed. More...
 

Friends

class VFS_session
 
class VFS_thread
 

Detailed Description

VFS_node is the base class from which all other VFS_node classes derive.

A VFS_node contains all the necessary apparatus for sending and receiving requests, executing them, managing children, managing subscriptions, notifying subscribers, etc.

The VFS is a tree of VFS_node entries where VFS is the root node.

Definition at line 142 of file VFS_node.h.

Constructor & Destructor Documentation

◆ VFS_node()

VFS_node::VFS_node ( )
explicit

The VFS_node constructor will add its instance to the VFS_node::__allNodes global node registry, observing thread safety rules.

Definition at line 515 of file VFS_node.cpp.

◆ ~VFS_node()

VFS_node::~VFS_node ( )
virtual

VFS_node destructor.

__removeNode() from the global registry, and recursively destroy all children.

Because this is modifying the object, it uses the VFS_node::_lock mutex.

Definition at line 531 of file VFS_node.cpp.

Member Function Documentation

◆ __addNode()

void VFS_node::__addNode ( VFS_node n)
staticprivate

Add a node to the global registry.

Parameters
nThe node to add

This will lock the static global VFS_node::__allNodesMutex

Definition at line 603 of file VFS_node.cpp.

◆ __isNode()

bool VFS_node::__isNode ( VFS_node n)
static

Check to see if a node is in the global registry.

Parameters
nThe VFS_node to check
Returns
boolean existence of the node

This will lock the static global VFS_node::__allNodesMutex

Definition at line 588 of file VFS_node.cpp.

◆ __removeNode()

bool VFS_node::__removeNode ( VFS_node n)
staticprivate

Remove a node from the global registry.

Parameters
nThe node to remove
Returns
boolean if the node removal was successful.

Definition at line 617 of file VFS_node.cpp.

◆ aclDefaults()

void VFS_node::aclDefaults ( VFS_request r)
protectedvirtual

Return default values and features associated wth this node.

Parameters
rThe VFS_request object

The un-subclassed case will return { "default":true }, which will allow access in all cases.

Note
A subclass that does provide a default in aclDefaults will produce a confusing interface, where the default may be true, but the aclEditor interface will show false until explicitly set.
See also
users_acl

Reimplemented in aclEditor, admin, and sessionsList.

Definition at line 918 of file VFS_node.cpp.

◆ addACLDefault()

void VFS_node::addACLDefault ( QJsonObject &  acl,
bool  value,
QString  description = "" 
)
protected

Add a default value to the acl object.

Parameters
aclThe QJsonObject being used as the ACL
valueThe default value for this VFS_node
descriptionAn optional description about the ACL entry that appears as a tooltip in the editor
{c++}
void myFancyNode::aclDefaults(VFS_request *r)
{
QJsonObject acl;
addACLDefault( acl, true );
r->_data.setObject(acl);
r->_success = true;
}
void addACLDefault(QJsonObject &acl, bool value, QString description="")
Add a default value to the acl object.
Definition: VFS_node.cpp:2131
The base class for all requests between nodes.
Definition: VFS_node.h:54
bool _success
if the request was successfully completed
Definition: VFS_node.h:107
QJsonDocument _data
the request payload
Definition: VFS_node.h:102

Note that this modifies the incoming acl object.

Definition at line 2131 of file VFS_node.cpp.

◆ addACLFeature()

void VFS_node::addACLFeature ( QJsonObject &  acl,
QString  feature,
bool  value,
QString  description = "" 
)
protected

Add a feature to the acl object.

Parameters
aclThe QJsonObject being used as the ACL
featureThe feature to add
valueThe default access value for this feature
descriptionAn optional description that appears as a tooltip in the aclEditor

Note that this modifies the incoming acl object.

Definition at line 2183 of file VFS_node.cpp.

◆ addACLFeatureGroup()

void VFS_node::addACLFeatureGroup ( QJsonObject &  acl,
QString  feature,
QString  group,
bool  value 
)
protected

Add a feature group to the acl object.

Parameters
aclThe QJsonObject being used as the ACL
featureThe application feature
groupThe group to add to the feature
valueThe access value for this feature's group list

Note that this modifies the incoming acl object.

Definition at line 2205 of file VFS_node.cpp.

◆ addACLFeatureUser()

void VFS_node::addACLFeatureUser ( QJsonObject &  acl,
QString  feature,
QString  user,
bool  value 
)
protected

Add a feature user to the acl object.

Parameters
aclThe QJsonObject being used as the ACL
featureThe application feature
userThe user to add to the feature
valueThe access value for this feature's user list

Note that this modifies the incoming acl object.

Definition at line 2227 of file VFS_node.cpp.

◆ addACLGroup()

void VFS_node::addACLGroup ( QJsonObject &  acl,
QString  group,
bool  value 
)
protected

Add a group to the acl object.

Parameters
aclThe QJsonObject being used as the ACL
groupThe group name to add
valueThe acces value for the group

Note that this modifies the incoming acl object.

Definition at line 2148 of file VFS_node.cpp.

◆ addACLUser()

void VFS_node::addACLUser ( QJsonObject &  acl,
QString  user,
bool  value 
)
protected

Add a user to the acl object.

Parameters
aclThe QJsonObject being used as the ACL
userThe user to add
valueThe access value for the user

Note that this modifies the incoming acl object.

Definition at line 2165 of file VFS_node.cpp.

◆ append()

VFS_node * VFS_node::append ( QString  name,
VFS_node node,
bool  containerCheck = true,
QString  user = "server" 
)
virtual

Append a VFS_node as a child of this node.

Parameters
nameThe child name
nodeThe VFS_node instance pointer
containerCheckNormally children can only be added to nodes where isContainer()=true. This is an override.
userThe user adding the node, used for logging.
Returns
The added node, or nullptr if unable to add.

This is the main mechanism for creating a VFS tree.

Reimplemented in VFS_ephemeral, and VFS_thread.

Definition at line 1566 of file VFS_node.cpp.

◆ applyDiff

void VFS_node::applyDiff ( VFS_request r)
virtualslot

Apply a diff received via subscription.

Parameters
rThe VFS_request object

The base class implementation calls notifySubscribers(), which will re-distribute a diff received from a subscription to this node's subscribers using VFS_node::notifySubscribers().

Subclass implementations may call submit(r), or perform more complex diff operations.

Attention
A subclass should only call this base class implementation if the subclass implementation does not cause a diff() to be emitted. This is very important to prevent duplicate notifications.
See also
VFS_HD::applyDiff()
VFS_remotoserver_client::applyDiff()

Definition at line 1463 of file VFS_node.cpp.

◆ className()

QString VFS_node::className ( )

Return the class name of a node.

Returns
The class name

The class name is fetched from Qt's metaObject(), which is useful for debug logging or fake user strings. Be sure to use the Q_OBJECT in a class definition to populate the metaObject.

Definition at line 2039 of file VFS_node.cpp.

◆ code()

QString VFS_node::code ( QString  nodename,
QString  libname,
QString &  error 
)
static

Fetch code or any other resource from a node.

Parameters
nodenameThe nodename or namespace for the request
libnameThe library requested
errorA reference to an error string, for writing errors back to the caller
Returns
The raw source code or resource requested.

The base class implementation returns nothing, and writes an error string to error.

A plugin could choose to load data from disk rather than a Qt resource. This would offer the benefit of not needing to recompile the plugin and restart the server for each change, but with the disadvantage of not having a fully encapsulated distribution package.

See also
VFS_node_interface::code()
VFS_creator::code()

Definition at line 1038 of file VFS_node.cpp.

◆ createRequest()

VFS_request * VFS_node::createRequest ( VFS_request::requestType  type,
QString  path,
QString  user = "unknown",
QJsonDocument  data = QJsonDocument(),
QJsonObject  metadata = QJsonObject(),
bool  dontDelete = false 
)
virtual

Create a new VFS_request with this object as _origin.

Parameters
typeThe request type
pathThe request path
userThe user who is performing the request
dataThe request data
metadataThe request metadata
dontDeleteA flag indicating whether the request is to be deleted when complete
Returns
The new VFS_request with this set as the _origin.

This is a convenience function, as sometimes it's not clear who is the _origin and who is the _receiver of a VFS_request.

Also, this can be subclassed to return a variant of a VFS_request, which is useful for some classes like VFS_remotoserver, who needs to use VFS_remotoserver_request for websocket communication.

The dontDelete flag should be rarely used, and only in cases where an inline VFS_request is being made on the same thread and the result is needed for later operations. Use at your own risk!

See also
VFS_remotoserver

Reimplemented in VFS_remotoserver_client.

Definition at line 1913 of file VFS_node.cpp.

◆ diff

void VFS_node::diff ( VFS_node origin,
VFS_request t 
)
signal

Emit a diff, which will trigger notifySubscribers() for a mounted node.

◆ executeRequest

void VFS_node::executeRequest ( VFS_request t)
virtualslot

Based on the VFS_request::requestType, execute the function associated with an operation.

Parameters
tThe VFS_request object

See the Commands page for a table of these calls.

After the command function is executed, issueResponse() is called if the request does not have a callback.

See also
Commands

Definition at line 1809 of file VFS_node.cpp.

◆ find() [1/2]

VFS_node * VFS_node::find ( QString  path)

Find a node by string path.

Parameters
pathThe path, from this VFS_node, to search
Returns
The found node, or null if not found.
Warning
This is scheduled for removal. It is a convenience function that obfuscates the nature of the find command, namely that a find can result in a path fragment, which is currently being thrown away.
See also
VFS_node::find(VFS_request *r)

Definition at line 1100 of file VFS_node.cpp.

◆ find() [2/2]

VFS_node * VFS_node::find ( VFS_request r)
virtual

Find a node using a VFS_request.

Parameters
rThe VFS_request object
Returns
The found node, or nullptr if not found.

The find function has many nuances, especially in the context of complex subclasses. Strictly speaking, the find() method will explode a path, take the first path entry, and search for a child with a matching name. If one is found, this will be repeated on the child.

More complex VFS_node subclasses represent virtual filesystem boundaries, for instance: VFS_thread, VFS_tcp_client, VFS_HD. If a node represents a barrier, it will return itself (this) as the found node, which will result in a path fragment. The expectation is that the node will use the path fragment (r->_path) to complete its operation by redirecting to somewhere else.

For instance, a VFS_HD node will always return itself for find(), and then use the path fragment plus its filesystem prefix to finally have access to a file on a hard disk.

Or, a VFS_thread will always return itself and then issue the request, with the remaining path parts to its _node, which preserves thread safety.

It is not a valid assumption to think that a find() will result in the node type you are interested in. It will often return a node at a filesystem boundary, so therefore typecasting a find() result is usually not possible unless you are sure of the nature of the path being searched.

See also
VFS_HD
VFS_thread

Reimplemented in logView, VFS_auth, VFS_sessionManager, VFS_acl, VFS_application, VFS_logger, VFS_thread, VFS_datastore, VFS_ephemeral, VFS_QRC, VFS_cron, VFS_tcp_mount, VFS_remotoserver_client, and VFS_threadpool.

Definition at line 1135 of file VFS_node.cpp.

◆ findChildWithName()

VFS_node * VFS_node::findChildWithName ( QString  name)

Check if a child with a given name exists.

Parameters
nameThe name to search
Returns
The child VFS_node, if it exists, or null

This is different from VFS_node::find() in that it does not search recursively and does not support meta entries. Only _children is searched by exact name.

Definition at line 2078 of file VFS_node.cpp.

◆ finished

void VFS_node::finished ( bool  andDelete = false)
signal

Emitted if a thread fails to create its node, or a node is rm()'d, or any other reason a node has completed its lifecycle. It is deleted if andDelete==true.

◆ icon()

QByteArray VFS_node::icon ( )
protectedvirtual

Fetch the icon for a node.

Returns
The icon in base64 or svg format, prepended with a mime

Icons are formatted to be placed directly in HTML tags (for instance, the 'src' field of an <img>). Subclasses will want to provide their own icons, or use an entry from VFS_icons. By default, if isContainer()==true, a folder icon will be returned, otherwise a document icon.

The icon returned should include mime type, encoding, and image data, as specified in RFC 2397.

Note
When creating custom icons, the '#' character (as used in color values) is reserved for use in URLs. '#' can be replaced with '%23', or an HTML color name (like 'red' or 'blue') can be used instead. Alternatively, base64-encoded image data can be returned.
//an inline SVG document icon with no encoding
return (char *) "data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"48\" height=\"48\" viewBox=\"0 -1.8 46.259 49.859\" vector-effect=\"non-scaling-stroke\" stroke=\"black\" fill=\"white\"><path d=\"M35.043 13.514a6.154 6.154 0 0 1-6.164-6.153V.797A.797.797 0 0 0 28.082 0H8.278a4.607 4.607 0 0 0-4.607 4.6v37.059c0 2.54 2.067 4.6 4.607 4.6h29.7a4.608 4.608 0 0 0 4.609-4.6V14.311a.796.796 0 0 0-.797-.797h-6.747z\"/><path d=\"M35.043 10.395h5.519a.795.795 0 0 0 .56-1.361 4304.06 4304.06 0 0 0-7.77-7.707.796.796 0 0 0-1.355.566v5.468c.001 1.665 1.38 3.034 3.046 3.034z\" /></svg>";
//an inline PNG from a resource file, with base64 encoding
return "data:image/png;base64,"+ rutils::resourceContents(iconPath).toBase64();
QByteArray resourceContents(QString resource, bool *ok=nullptr, bool squashHash=false)
Fetch the contents of a Qt resource file.
Definition: rutils.cpp:53
See also
VFS_icons

Reimplemented in aclEditor, admin, cpuUsage, logView, sessionsList, VFS_mongo, VFS, VFS_auth, VFS_session, VFS_sessionManager, VFS_application, VFS_ephemeral, VFS_HD, VFS_cron, VFS_curl, VFS_iframe, VFS_stream, VFS_tcp_export, and VFS_tcp_mount.

Definition at line 655 of file VFS_node.cpp.

◆ isContainer()

bool VFS_node::isContainer ( )
virtual

A VFS_node may have children.

This flag determines whether or not they are allowed.

Returns
bool container-ness of a node

By default, all VFS_nodes are containers.

Generally, this method is overridden in a subclass to return a hardcoded true or false depending on the nature of the node.

A node that is a container can append() children, and in directory listings, a container node will appear as a directory.

Note
This definition is a little fuzzy, and ultimately the desire is to deprecate this concept. It's entirely possible for a non-container node to present virtual children as a series of paths, or to appear browsable even though it bypasses the default parent/child apparatus common to all VFS_node implementations.

Reimplemented in aclEditor, cpuUsage, sessionsList, VFS_auth, VFS_session, VFS_acl, VFS_thread, VFS_datastore, VFS_ephemeral, VFS_QRC, VFS_cron, VFS_curl, VFS_pulse, VFS_stream, VFS_httpd, VFS_tcp_client, VFS_tcp_server, VFS_tcp_mount, VFS_udp_socket, VFS_websocket_client, VFS_websocket_server, and VFS_threadpool.

Definition at line 2025 of file VFS_node.cpp.

◆ issueRequest() [1/2]

void VFS_node::issueRequest ( VFS_node target,
VFS_request t 
)
protectedvirtual

Issue a VFS_request to its target.

Parameters
targetThe target of the request
tThe VFS_request object

This will call subtreeRequest() on the target node by calling it as a slot. Thread safety is observed by calling __isNode().

Note that t->_path should be relative to the target node, not necessarily the VFS::root()

If t->_path=="", then the target will directly execute the request, because find() will immediately return.

See also
VFS_node::subtreeRequest()
Requests

Definition at line 1955 of file VFS_node.cpp.

◆ issueRequest() [2/2]

void VFS_node::issueRequest ( VFS_request t)
protectedvirtual

A convenience function.

Parameters
tThe VFS_request object

This is equivalent to:

virtual void issueRequest(VFS_request *t)
A convenience function.
Definition: VFS_node.cpp:1933
static VFS * root()
Return the root node of the VFS filesystem.
Definition: VFS.cpp:399
See also
issueRequest(VFS_node *node, VFS_request *t)

Definition at line 1933 of file VFS_node.cpp.

◆ issueResponse()

void VFS_node::issueResponse ( VFS_request t)
protectedvirtual

Once a request has been completed, issue a response.

Parameters
tThe VFS_request object

This is usually called at the end of executeRequest(), and will issue a payload to the receiveResponse() slot. Thread safety is maintained using __isNode().

See also
VFS_node::receiveResponse()
Requests

Definition at line 1981 of file VFS_node.cpp.

◆ ls()

void VFS_node::ls ( VFS_request r)
protectedvirtual

List the contents of this node.

Parameters
rThe VFS_request object

List format will be:

{
"dir1": true,
"dir2": true,
"file1": false
}

Where each child is listed with the status of isContainer(). This will allow the receiver to know whether or not a child entry can be recursed.

The assumption is that if isContainer()==false, the sub-path supports VFS requests like read(), submit(), or subscribe()

Subclasses may choose to list additional virtual children if desired. Those entries will need to be added to find() to be effective.

See also
Requests

Reimplemented in google_oauth2, VFS_mongo, VFS_pam, VFS_curlauth, VFS_nopasswd, VFS_passwd, VFS_application, VFS_ephemeral, VFS_HD, VFS_QRC, and VFS_cron.

Definition at line 692 of file VFS_node.cpp.

◆ metadata()

void VFS_node::metadata ( VFS_request r)
protectedvirtual

Fetch the metadata of this node.

Parameters
rThe VFS_request object

The base implementation will call icon() to populate the r->_metadata["icon"] field.

Generally, the metadata will want to contain "icon" and "type" fields, but could contain anything. It is recommended that classes call their parent implementation before modifying the metadata:

void myFancyNode::metadata(VFS_request *r)
{
r->_metadata["type"] = "fancy";
//now we have "icon" and "type" entries.
}
virtual void metadata(VFS_request *r)
Fetch the metadata of this node.
Definition: VFS_node.cpp:797
QJsonObject _metadata
the request payload
Definition: VFS_node.h:101
See also
Requests

Reimplemented in aclEditor, admin, cpuUsage, logView, sessionsList, VFS_mongo, VFS_ephemeral, VFS_HD, VFS_QRC, VFS_applications, VFS_curl, VFS_iframe, VFS_stream, and VFS_tcp_server.

Definition at line 797 of file VFS_node.cpp.

◆ mount()

VFS_node * VFS_node::mount ( )
virtual

Mount this node.

Returns
this

This will make a signal/slot connection from this::diff to this::notifySubscribers(). The idea is that an unmounted node cannot emit meaningful diffs, as it's not part of the filesystem.

When mount() is called, the node will emit mounted(), which can be a useful trigger for other operations.

A node may choose to subclass this, however the base implementation should always be called.

Reimplemented in VFS_thread.

Definition at line 1718 of file VFS_node.cpp.

◆ mounted

void VFS_node::mounted ( )
signal

Emitted when a node is mount()ed.

◆ notifySubscribers

void VFS_node::notifySubscribers ( VFS_node origin,
VFS_request t 
)
slot

Propagate a diff to subscribers.

Parameters
originThe VFS_node that the redistributed VFS_requests will use as _origin
tThe diff VFS_request to redistribute

Iterate over the _subscribers list, and build a new VFS_request for each subscriber which contains the data from the diff VFS_request. The new VFS_request object is sent to the executeRequest() slot for each subscriber.

If the request's VFS_request::_data and VFS_request::_metadata are both empty, this function will abort, since no meaningful data will be propagated.

Usually if a client calls submit() to a VFS_node that it's already subscribed to, it doesn't need to receive the diff back, because it was the node that originated the request. The VFS_request::_notifyExceptions list keeps track of which subscribers are not to be sent data for this request. This method will check to see if an exception exists, and if so, it will skip that subscriber.

Because VFS_request::_notifyExceptions is public, nodes can be added any time during a request's lifecycle, however this is the only place that the exception is checked and used. Be aware of thread safety when adding notify exceptions!

Note
This method should never be subclassed, and is therefore not virtual.
See also
diff()

Definition at line 1497 of file VFS_node.cpp.

◆ read()

void VFS_node::read ( VFS_request r)
protectedvirtual

Return the data contents of this node, or if it's a container call ls()

Parameters
rThe VFS_request object

The base class implementation will return no data and _success will be false, except for the case of isContainer()==true, where ls() will be performed.

Data should be written to VFS_request::_data, and can be any JSON content.

Note that if a pane is subscribing to a node, the VFS_client will close panes that receive null as content. Even if you plan to do nothing with the read value of a node, you should provide some non-null data to prevent the pane from closing, or failing to open.

See also
Requests

Reimplemented in aclEditor, admin, cpuUsage, logView, sessionsList, google_oauth2, VFS_mongo, VFS_pam, VFS_curlauth, VFS_nopasswd, VFS_passwd, VFS_session, VFS_sessionManager, VFS_acl, VFS_ephemeral, VFS_HD, VFS_QRC, VFS_cron, VFS_curl, VFS_iframe, VFS_pulse, VFS_stream, and VFS_tcp_server.

Definition at line 724 of file VFS_node.cpp.

◆ receiveResponse

void VFS_node::receiveResponse ( VFS_request t)
virtualslot

Once a VFS_request has been completed, a response will be issued back to its _origin.

Parameters
tThe VFS_request object

At this point, VFS_request::execute() will be called. If the VFS_request has a callback request, the payload is copied to the callback object, and issueResponse() is called for the callback request.

The VFS_request is then deleted using VFS_request::~VFS_request(), the destructor.

Attention
In subclasses, this base class implementation should always be called.
See also
VFS_node::issueResponse()
Requests

Definition at line 1870 of file VFS_node.cpp.

◆ releaseLock()

void VFS_node::releaseLock ( VFS_request r)
protectedvirtual

Release a lock on this node.

Parameters
rThe VFS_request object

Subclasses of VFS_node can choose to implement locking however they see fit. This can be on the node level or on an individual field; it is up to the implementer to do these checks.

Definition at line 1081 of file VFS_node.cpp.

◆ remove [1/2]

void VFS_node::remove ( bool  andDelete)
slot

Remove a child node.

Parameters
andDeleteOptionally delete the node

This is a convenience slot. It will use the sender of the signal as the target node for removal.

The andDelete option will call node->deleteLater(), which will happen when the event queue has emptied.

Definition at line 1629 of file VFS_node.cpp.

◆ remove [2/2]

void VFS_node::remove ( VFS_node node = nullptr,
QString *  rname = nullptr,
QString  user = "server" 
)
virtualslot

Remove a child node from this node.

Parameters
nodeThe node to remove, or null if a signal sender is to be used.
rnameA string to write the deleted node's name back to.
userA user string to use for logging.

Check to make sure the node is a child of this node. If it is, disconnect the finished() signal, and unmount() it. Note the change to this node by emitting a diff with a null value for the child name. This is really only meaningful for nodes with isContainer()==true.

Although the node has been removed, it has not necessarily been deleted. It may be remounted elsewhere.

Definition at line 1660 of file VFS_node.cpp.

◆ report()

void VFS_node::report ( VFS_request r)
protectedvirtual

Report debugging information about the current state of this node.

Parameters
rThe VFS_request

Used for debugging, return the subscription state and child list for this node. It will also provide a thread address and a few other things.

This can be viewed using the VFS_httpd_browser.

See also
VFS_httpd_browser

Definition at line 817 of file VFS_node.cpp.

◆ reportDetails()

QString VFS_node::reportDetails ( )
virtual

Additional details for a generated report.

Returns
A string containing the additional details.

This is useful in subclasses for providing class-specific information of any kind. For instance, VFS_cron::reportDetails() will list all active events.

See also
VFS_httpd_browser

Reimplemented in google_oauth2, VFS_mongo, VFS_pam, VFS_nopasswd, VFS_passwd, VFS_session, VFS_sessionManager, VFS_acl, VFS_datastore, VFS_ephemeral, VFS_HD, VFS_cron, VFS_curl, VFS_iframe, VFS_stream, VFS_tcp_client, VFS_tcp_server, VFS_tcp_export, VFS_udp_socket, VFS_remotoserver, and VFS_remotoserver_client.

Definition at line 900 of file VFS_node.cpp.

◆ requestLock()

void VFS_node::requestLock ( VFS_request r)
protectedvirtual

Request a lock on this node.

Parameters
rThe VFS_request object

Subclasses of VFS_node can choose to implement locking however they see fit. This can be on the node level or on an individual field; it is up to the implementer to do these checks.

Definition at line 1065 of file VFS_node.cpp.

◆ rm()

void VFS_node::rm ( VFS_request r)
protectedvirtual

Remove a child entry from a node, or the node itself.

Parameters
rThe VFS_request

A rm() operation will delete VFS_node entries. This is very nuanced. The intention is that find() will have navigated to a node, consuming path prefixes as it goes. When find is complete for a normal node, r->_path will be an empty string. More complex nodes with virtual children will need to use r->_path to determine an action.

By default, rm() will check for the non-existence of children, and an empty path. If those conditions are met, it will then emit finished(true), to signal the parent to remove() the child and call its destructor.

rm() should always set r->_success to a proper state.

Note
when calling rm() to remove a node, the parent is experiencing a change, which will cause emit diff() to be called. This way, directory views in a user interface will stay consistent if a user has subscribed to the parent.

Reimplemented in VFS_mongo, VFS_session, VFS_HD, VFS_QRC, and VFS_remotoserver_client.

Definition at line 1005 of file VFS_node.cpp.

◆ submit()

void VFS_node::submit ( VFS_request r)
protectedvirtual

Submit a diff to a node.

Parameters
rThe VFS_request object

A submit() operation will apply a diff to the contents of a node. The base class implementation will report a warning, but _success will be true and a diff will be emitted.

Subclasses will want to apply the incoming diff, and if successful, emit a diff(). The emit is the notification mechanism for cascading changes to subscribers.

class myFancyNode : public VFS_node
{
Q_OBJECT
public:
QJsonObject _data;
protected:
virtual void submit(VFS_request *r);
}
void myFancyNode::submit(VFS_request *r)
{
QJsonObject o = r->_data.toObject();
if (r->_path == "")
if (o.contains["fancy"])
{
QJsonValue v = o["fancy"];
if (v.isNull())
_data.remove("fancy");
else if (v.isString())
_data["fancy"] = o["fancy"].toString();
else
{ r->_success = false;
return;
}
r->_success = true;
emit diff(this, r);
}
r->_success = false;
}
VFS_node is the base class from which all other VFS_node classes derive.
Definition: VFS_node.h:143
virtual void submit(VFS_request *r)
Submit a diff to a node.
Definition: VFS_node.cpp:978
void diff(VFS_node *origin, VFS_request *t)
Emit a diff, which will trigger notifySubscribers() for a mounted node.
QString _path
the target path remnant... the remaining path element once the request has found its target
Definition: VFS_node.h:95
See also
Requests
Diffs
VFS_HD

Reimplemented in VFS_mongo, VFS_acl, VFS_logger, VFS_ephemeral, VFS_HD, VFS_QRC, VFS_stream, and VFS_websocket_client.

Definition at line 978 of file VFS_node.cpp.

◆ subscribe()

void VFS_node::subscribe ( VFS_request r)
protectedvirtual

Add an entry to this node's _subscription list.

Parameters
rThe VFS_request object

When a VFS node subscribes to a path on the VFS, subtreeRequest() will call find() to arrive at the node needed to create a subscription entry. An entry in the found node's VFS_node::_subscribers object is made which points back to the subscriber. The path fragment remaining after the find() is used as a key for the subscription entry.

An entry may already exist for that path and subscriber combination, in which case the subscription count is incremented here. The subscription count will decrement on unsubscribe(). If the subscription count becomes zero, the entry is removed.

This pattern would allow, for instance, 10 gui elements from one client to subscribe to a path, and as long as any one of them remains subscribed, the client would receive diffs.

When a subscription is requested, the node will execute a metadata() and read() call to populate the VFS_request object with initial data from the node. Otherwise, a client would need to immediately request a metadata() and read(), but because the system works asynchronously between threads, and the requests could be going over (a potentially slow) network, this would not work.

Care is taken that if a node exists in a VFS_node::_subscribers list, this node creates a connection to its unmounted() signal so that it can be removed, effectively unsubscribing it. The unmounted() signal is part of a VFS_node::~VFS_node()'s destructor sequence.

Please note that if a node intends to chain subscriptions together using a callback, the metadata() call will actually be a VFS_request::subscribe call. This is confusing at first, but is the desired functionality. To rephrase, if subscribing to a node causes that node to subscribe to another node, we want to satisfy the original request by populating the _data and _metadata fields of the request, while also creating subscription links between intermediate nodes. All of this comes for free, but is a little obfusticated in the simplicity of the call. The initial node being subscribed to will pass the request to subnodes by aborting the subscribe function when r->_success is not true or r->_callback exists.

The special metadata flag r->_metadata["__SUBSCRIBE_ONLY__"]=true exists for the case when one wants to subscribe to a path, but doesn't care about receiving the node's data upon subscription.

Todo:
Create circular subscription check for VFS_node
See also
unsubscribe()
Requests

Reimplemented in VFS_mongo, VFS_acl, VFS_HD, VFS_QRC, and VFS_cron.

Definition at line 1204 of file VFS_node.cpp.

◆ subtreeRequest

void VFS_node::subtreeRequest ( VFS_request t)
virtualslot

find() the target of a VFS_request, and execute the request

Parameters
tThe VFS_request object

If the result of find() is null, the request is marked _success=false and issueResponse() is called. Otherwise the VFS_request is sent to the found node's executeRequest().

It's important to note that this is called in the thread that will actually be doing the execution.

See also
issueRequest()

Definition at line 1767 of file VFS_node.cpp.

◆ uniqueChildName()

QString VFS_node::uniqueChildName ( QString  name)

Generate a unique child name.

Parameters
nameThe start name
Returns
A unique name

This will add a incremented number to the end of the provided name. Child names must be unique. }

Definition at line 2054 of file VFS_node.cpp.

◆ unmount()

VFS_node * VFS_node::unmount ( )
virtual

Unmount this node.

Returns
this

This will remove the signal/slot connection from this::diff to this::notifySubscribers().

When unmount() is called, the node will emit unmounted(), which can be a useful trigger for other operations.

A node may choose to subclass this, however the base implementation should always be called.

Reimplemented in VFS_thread.

Definition at line 1742 of file VFS_node.cpp.

◆ unmounted

void VFS_node::unmounted ( VFS_node self)
signal

Emitted when a node is unmount()ed.

◆ unsubscribe()

void VFS_node::unsubscribe ( VFS_request r)
protectedvirtual

Remove an entry from this node's _subscription list.

Parameters
rThe VFS_request object

When a VFS_node unsubscribes from a path on the VFS, subtreeRequest() will call find() to arrive at the node the needs to remove the _subscription entry.

If _subscribers has an r->_path entry, and within that an r->_originPath entry, and within that an r->_origin entry, then r->_metadata["unsubscriptions"] or a default 1 will be used to know how far to decrement the subscription count.

As counts are decremented, fields are removed when empty. If all references to a subscriber node are removed from this subscription list, the unmounted() connection to it is removed from this node.

See also
subscribe()

Reimplemented in VFS_acl, and VFS_cron.

Definition at line 1263 of file VFS_node.cpp.

◆ unsubscribeAll

void VFS_node::unsubscribeAll ( VFS_node subscriber)
virtualslot

Remove all references to a subscriber from this node.

Parameters
subscriberThe VFS_node to remove.

This requires iterating over the whole _subscribers node, which may be expensive on a large set.

This function is called when a node is unmounted(), so that all subscription references are removed.

Definition at line 1336 of file VFS_node.cpp.

◆ unsubscribePath()

void VFS_node::unsubscribePath ( QString  path)
protectedvirtual

Unsubscribe all references to a subpath.

Parameters
pathThe path to remove

This method removes all references to a given path from the _subscribers list. This may be desired if files are removed from a VFS_HD node and therefore a path no longer exists.

For each node/path that was subscribed, emit a diff with null contents to notify subscribers of the removal.

Definition at line 1384 of file VFS_node.cpp.

◆ validChildName()

bool VFS_node::validChildName ( QString  name)
virtual

Check if a node name is valid.

Parameters
nameThe name to check
Returns
boolean validity of name

A valid name will:

  • not be empty (even when trimmed)
  • not contain '/'
  • not start or end with whitespace
Warning
Because this function is virtual, this functionality can be overridden. DO SO AT YOUR OWN RISK! It is virtual so the functionality can be augmented, but unpredictable things will break if the base class function is not called.

Definition at line 2101 of file VFS_node.cpp.

◆ write()

void VFS_node::write ( VFS_request r)
protectedvirtual

Write data to this node.

Parameters
rThe VFS_request object

A write() operation replaces the data contents of a node. The base class implementation will do nothing and _success will be false.

For subclasses, this may be used to issue commands, replace entire files, or any other purpose. This is in contrast to submit(), which will attempt to apply a diff to data.

A write() operation should emit a diff() if it is successful. The emit is the notification mechanism for cascading changes to subscribers.

void myFancyNode::write(VFS_request *r)
{
this._data = r->_data;
//modify r->_data or r->_metadata here if needed
//optionally a new VFS_request could be created here with different diff data to emit
r->_success = true;
emit diff(this, r);
}
See also
Requests

Reimplemented in VFS_mongo, VFS_sessionManager, VFS_ephemeral, VFS_HD, VFS_QRC, VFS_stream, VFS_tcp_client, VFS_udp_socket, VFS_remotoserver_client, and VFS_websocket_client.

Definition at line 767 of file VFS_node.cpp.

Friends And Related Function Documentation

◆ VFS_session

friend class VFS_session
friend

Definition at line 146 of file VFS_node.h.

◆ VFS_thread

friend class VFS_thread
friend

Definition at line 147 of file VFS_node.h.

Member Data Documentation

◆ __allNodes

QSet< VFS_node * > VFS_node::__allNodes
staticprivate

The static global registry for all exiting nodes, used for thread safety checks.

Definition at line 215 of file VFS_node.h.

◆ __allNodesMutex

QMutex VFS_node::__allNodesMutex
staticprivate

The global registry mutex, which will lock when node creation or deletion is being performed.

Definition at line 216 of file VFS_node.h.

◆ _children

VFS_children VFS_node::_children
protected

This node's children.

Definition at line 179 of file VFS_node.h.

◆ _lock

QMutex VFS_node::_lock
mutableprotected

A recursive mutex that is local to this node.

Definition at line 178 of file VFS_node.h.

◆ _subscribers

VFS_subscriptionType VFS_node::_subscribers
protected

This node's subscribers. These subscribers will receive diff notifications.

Definition at line 180 of file VFS_node.h.


The documentation for this class was generated from the following files: