diff --git a/src/kits/storage/NodeMonitor.cpp b/src/kits/storage/NodeMonitor.cpp new file mode 100644 index 0000000000..c48f3c236c --- /dev/null +++ b/src/kits/storage/NodeMonitor.cpp @@ -0,0 +1,217 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- + +#include +#include +#include +#include + +// TODO: Tests! + +// private libroot.so functions + +/*! \brief Subscribes a target to node and/or mount watching. + + Depending on \a flags, different actions are performed. If flags is \c 0, + mount watching is requested. \a device and \a node must be \c -1 in this + case. Otherwise node watching is requested. \a device and \a node must + refer to a valid node, and \a flags must note contain the flag + \c B_WATCH_MOUNT, but at least one of the other valid flags. + + \param device The device the node resides on (node_ref::device). \c -1, if + only mount watching is requested. + \param node The node ID of the node (node_ref::device). \c -1, if + only mount watching is requested. + \param flags A bit mask composed of the values specified in + . + \param port The port of the target (a looper port). + \param handlerToken The token of the target handler. \c -2, if the + preferred handler of the looper is the target. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +extern "C" status_t _kstart_watching_vnode_(dev_t device, ino_t node, + uint32 flags, port_id port, + int32 handlerToken); + +/*! \brief Unsubscribes a target from watching a node. + \param device The device the node resides on (node_ref::device). + \param node The node ID of the node (node_ref::device). + \param port The port of the target (a looper port). + \param handlerToken The token of the target handler. \c -2, if the + preferred handler of the looper is the target. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +extern "C" status_t _kstop_watching_vnode_(dev_t device, ino_t node, + port_id port, int32 handlerToken); + + +/*! \brief Unsubscribes a target from node and mount monitoring. + \param port The port of the target (a looper port). + \param handlerToken The token of the target handler. \c -2, if the + preferred handler of the looper is the target. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +extern "C" status_t _kstop_notifying_(port_id port, int32 handlerToken); + + +// actual implementation + +// watch_node +/*! \brief Subscribes a target to node and/or mount watching, or unsubscribes + it from node watching. + + Depending of \a flags the action performed by this function varies: + - \a flags is \c 0: The target is unsubscribed from watching the node. + \a node must not be \c NULL in this case. + - \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount + watching. + - \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT, + \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to + watching the specified aspects of the node. \a node must not be \c NULL + in this case. + + Note, that the latter two cases are not mutual exlusive, i.e. mount and + node watching can be requested with a single call. + + \param node node_ref referring to the node to be watched. May be \c NULL, + if only mount watching is requested. + \param flags Flags indicating the actions to be performed. + \param target Messenger referring to the target. Must be valid. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +status_t +watch_node(const node_ref *node, uint32 flags, BMessenger target) +{ + status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); + if (error == B_OK) { + BLooper *looper = NULL; + BHandler *handler = target.Target(&looper); + error = watch_node(node, flags, handler, looper); + } + return error; +} + +// watch_node +/*! \brief Subscribes a target to node and/or mount watching, or unsubscribes + it from node watching. + + Depending of \a flags the action performed by this function varies: + - \a flags is \c 0: The target is unsubscribed from watching the node. + \a node must not be \c NULL in this case. + - \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount + watching. + - \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT, + \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to + watching the specified aspects of the node. \a node must not be \c NULL + in this case. + + Note, that the latter two cases are not mutual exlusive, i.e. mount and + node watching can be requested with a single call. + + \param node node_ref referring to the node to be watched. May be \c NULL, + if only mount watching is requested. + \param flags Flags indicating the actions to be performed. + \param handler The target handler. May be \c NULL, if \a looper is not + \c NULL. Then the preferred handler of the looper is targeted. + \param looper The target looper. May be \c NULL, if \a handler is not + \c NULL. Then the handler's looper is the target looper. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +status_t +watch_node(const node_ref *node, uint32 flags, const BHandler *handler, + const BLooper *looper) +{ + status_t error = B_OK; + // check looper and handler and get the handler token + int32 handlerToken = -2; + if (handler) { + handlerToken = _get_object_token_(handler); + if (looper) { + if (looper != handler->Looper()) + error = B_BAD_VALUE; + } else { + looper = handler->Looper(); + if (!looper) + error = B_BAD_VALUE; + } + } else if (!looper) + error = B_BAD_VALUE; + if (error == B_OK) { + port_id port = _get_looper_port_(looper); + if (flags == B_STOP_WATCHING) { + // unsubscribe from node node watching + if (node) { + error = _kstop_watching_vnode_(node->device, node->node, port, + handlerToken); + } else + error = B_BAD_VALUE; + } else { + // subscribe to... + // mount watching + if (flags & B_WATCH_MOUNT) { + error = _kstart_watching_vnode_(-1, -1, 0, port, handlerToken); + flags &= ~B_WATCH_MOUNT; + } + // node watching + if (error == B_OK && flags) { + error = _kstart_watching_vnode_(node->device, node->node, + flags, port, handlerToken); + } + } + } + return error; +} + +// stop_watching +/*! \brief Unsubscribes a target from node and mount monitoring. + \param target Messenger referring to the target. Must be valid. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +status_t +stop_watching(BMessenger target) +{ + status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); + if (error == B_OK) { + BLooper *looper = NULL; + BHandler *handler = target.Target(&looper); + error = stop_watching(handler, looper); + } + return error; +} + +// stop_watching +/*! \brief Unsubscribes a target from node and mount monitoring. + \param handler The target handler. May be \c NULL, if \a looper is not + \c NULL. Then the preferred handler of the looper is targeted. + \param looper The target looper. May be \c NULL, if \a handler is not + \c NULL. Then the handler's looper is the target looper. + \return \c B_OK, if everything went fine, another error code otherwise. +*/ +status_t +stop_watching(const BHandler *handler, const BLooper *looper) +{ + status_t error = B_OK; + // check looper and handler and get the handler token + int32 handlerToken = -2; + if (handler) { + handlerToken = _get_object_token_(handler); + if (looper) { + if (looper != handler->Looper()) + error = B_BAD_VALUE; + } else { + looper = handler->Looper(); + if (!looper) + error = B_BAD_VALUE; + } + } else if (!looper) + error = B_BAD_VALUE; + // unsubscribe + if (error == B_OK) { + port_id port = _get_looper_port_(looper); + error = _kstop_notifying_(port, handlerToken); + } + return error; +} + diff --git a/src/kits/storage/storage.src b/src/kits/storage/storage.src index b306ac7028..afe3ba291e 100644 --- a/src/kits/storage/storage.src +++ b/src/kits/storage/storage.src @@ -11,6 +11,7 @@ STORAGE_KIT_SOURCE = MimeType.cpp Node.cpp NodeInfo.cpp + NodeMonitor.cpp OffsetFile.cpp Path.cpp Query.cpp