cluck 1.0.1
The cluster lock service.
Public Types | Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
cluck::cluck Class Reference

Cluster lock. More...

#include <cluck.h>

Inheritance diagram for cluck::cluck:
Inheritance graph
[legend]
Collaboration diagram for cluck::cluck:
Collaboration graph
[legend]

Public Types

typedef snapdev::callback_manager< callback_tcallback_manager_t
 
typedef std::function< bool(cluck *)> callback_t
 
typedef std::shared_ptr< cluckpointer_t
 
typedef std::uint64_t serial_t
 

Public Member Functions

 cluck (std::string const &object_name, ed::connection_with_send_message::pointer_t connection, ed::dispatcher::pointer_t dispatcher, mode_t mode=mode_t::CLUCK_MODE_SIMPLE)
 Create a cluster lock.
 
virtual ~cluck () override
 Make sure to clean up the dispatcher.
 
callback_manager_t::callback_id_t add_finally_callback (callback_t func, callback_manager_t::priority_t priority=callback_manager_t::DEFAULT_PRIORITY)
 Add a callback function to call when done with the lock.
 
callback_manager_t::callback_id_t add_lock_failed_callback (callback_t func, callback_manager_t::priority_t priority=callback_manager_t::DEFAULT_PRIORITY)
 Add a callback function to call when the lock has failed.
 
callback_manager_t::callback_id_t add_lock_obtained_callback (callback_t func, callback_manager_t::priority_t priority=callback_manager_t::DEFAULT_PRIORITY)
 Add a callback function to call when the lock is obtained.
 
timeout_t get_lock_duration_timeout () const
 Retrieve the current lock duration.
 
timeout_t get_lock_obtention_timeout () const
 Retrieve the current lock obtention duration.
 
mode_t get_mode () const
 Retrieve the mode.
 
std::string const & get_object_name () const
 Retrieve the object name.
 
reason_t get_reason () const
 The reason for the last failure.
 
timeout_t get_timeout_date () const
 Get the exact time when the lock times out.
 
type_t get_type () const
 Retrieve the lock type.
 
timeout_t get_unlock_timeout () const
 Retrieve the current unlock duration.
 
bool is_busy () const
 Check whether the object is currently busy.
 
bool is_locked () const
 This function checks whether the lock is considered locked.
 
bool lock ()
 Attempt a lock.
 
virtual void process_timeout () override
 Process the timeout event.
 
bool remove_finally_callback (callback_manager_t::callback_id_t id)
 Remove a callback function from the lock finally list.
 
bool remove_lock_failed_callback (callback_manager_t::callback_id_t id)
 Remove a callback function from the lock failed list.
 
bool remove_lock_obtained_callback (callback_manager_t::callback_id_t id)
 Remove a callback function from the lock obtained list.
 
void set_lock_duration_timeout (timeout_t timeout)
 Set how long inter-process locks last.
 
void set_lock_obtention_timeout (timeout_t timeout)
 Set how long to wait for an inter-process lock to take.
 
void set_type (type_t type)
 Set the lock type.
 
void set_unlock_timeout (timeout_t timeout)
 Set how long we wait on an inter-process unlock acknowledgement.
 
void unlock ()
 Release the inter-process lock.
 

Protected Member Functions

virtual void finally ()
 The lock cycle is finally complete.
 
virtual void lock_failed ()
 The lock did not take or an error was reported.
 
virtual void lock_obtained ()
 This function gets called whenever the lock is in effect.
 

Private Member Functions

bool help (advgetopt::string_set_t &commands)
 Called whenever the HELP message is received or new messages are added.
 
bool is_cluck_msg (ed::message &msg) const
 Verify a message we received.
 
void msg_lock_failed (ed::message &msg)
 Process the LOCK_FAILED message.
 
void msg_locked (ed::message &msg)
 Process the LOCKED message.
 
void msg_transmission_report (ed::message &msg)
 Get a transmission report on errors.
 
void msg_unlocked (ed::message &msg)
 Process the UNLOCK acknowledgement.
 
void msg_unlocking (ed::message &msg)
 The cluckd service sent us an UNLOCKING message.
 
void set_reason (reason_t reason)
 Change the reason why a lock failed.
 

Private Attributes

ed::connection_with_send_message::pointer_t f_connection = ed::connection_with_send_message::pointer_t()
 
ed::dispatcher::pointer_t f_dispatcher = ed::dispatcher::pointer_t()
 
callback_manager_t f_finally_callbacks = callback_manager_t()
 
timeout_t f_lock_duration_timeout = CLUCK_DEFAULT_TIMEOUT
 
callback_manager_t f_lock_failed_callbacks = callback_manager_t()
 
callback_manager_t f_lock_obtained_callbacks = callback_manager_t()
 
timeout_t f_lock_obtention_timeout = CLUCK_DEFAULT_TIMEOUT
 
timeout_t f_lock_timeout_date = timeout_t()
 
mode_t f_mode = mode_t::CLUCK_MODE_SIMPLE
 
std::string f_object_name = std::string()
 
reason_t f_reason = reason_t::CLUCK_REASON_NONE
 
serial_t f_serial = serial_t()
 
state_t f_state = state_t::CLUCK_STATE_IDLE
 
ed::dispatcher_match::tag_t const f_tag = ed::dispatcher_match::DISPATCHER_MATCH_NO_TAG
 
type_t f_type = type_t::CLUCK_TYPE_READ_WRITE
 
timeout_t f_unlock_timeout = CLUCK_DEFAULT_TIMEOUT
 
timeout_t f_unlocked_timeout_date = timeout_t()
 

Detailed Description

This class is used to run code synchronously in a cluster of computers.

The class accepts three callbacks:

The cluck class is itself an eventdispatcher connection so you must add it to the communicator. Actually, you can add it and then forget about the pointer. That way, once you are in your finally code, it automatically gets removed from the communicator.

Definition at line 119 of file cluck.h.

Member Typedef Documentation

◆ callback_manager_t

typedef snapdev::callback_manager<callback_t> cluck::cluck::callback_manager_t

Definition at line 125 of file cluck.h.

◆ callback_t

typedef std::function<bool(cluck *)> cluck::cluck::callback_t

Definition at line 124 of file cluck.h.

◆ pointer_t

typedef std::shared_ptr<cluck> cluck::cluck::pointer_t

Definition at line 123 of file cluck.h.

◆ serial_t

typedef std::uint64_t cluck::cluck::serial_t

Definition at line 126 of file cluck.h.

Constructor & Destructor Documentation

◆ cluck()

cluck::cluck::cluck ( std::string const &  object_name,
ed::connection_with_send_message::pointer_t  messenger,
ed::dispatcher::pointer_t  dispatcher,
mode_t  mode = mode_t::CLUCK_MODE_SIMPLE 
)

The cluck object expects at least three parameters to offer the ability to create a cluster lock. A cluster lock allows you to run one or more functions in a cluster safe manner (i.e. by a single process running in a computer cluster of any size).

First, the function expects a object_name parameter. This is the name of the lock. To run a function within a single process, any number of processes can request a lock using the exact same object_name.

Second, the cluck object needs to send messages and for the purposes needs to have access to a connection that has the send_message() functionality implemented. In most likelihood, this is your communicator derived class (your messenger).

Third, the function has to react to replies from the messages it sends. This is accomplished by the dispatcher object. Again, this is likely your messenger dispatcher.

The constructor collects that data. The lock() function sets up the dispatcher callbacks and sends a LOCK message to the connection. The unlock() function is implemented as a failure, your error callbacks are called and then the finally callbacks, which removes the dispatcher callbacks. (Note: there are two sets of callbacks, the dispatcher callbacks are automatically managed, the success, error, and finally callbacks are managed by you, the cluck user.)

Many functions cannot be called once the lock() function was called, including the lock() function itself. These work again after the finally() function was called. This is done this way because some of the cluck parameters cannot or should not be changed while a lock is being processed.

The dispatcher expects to receive one of the LOCKED or LOCKFAILED messages after the LOCK was sent to the cluck service. Once done with a lock, we send an UNLOCK message and in that case we expected the UNLOCKED message as a reply. If a processes uses a LOCK for too long (i.e. the cluck service notices that the lock timed out), it may also receive the UNLOCKING message letting it know that the lock is about to be terminated. Your cluck objects react to that message by stopping the lock and you are expected to not run any additional cluster safe code since it may become unsafe at any moment.

Keep in mind that the object is used 100% asynchronously. If you want to execute code after the lock was released, make sure to also define a set of finally callbacks.

If the code you need to execute requires sending and receiving other messages (i.e. go back in the communicator run() loop), then it is required to use the mode_t::CLUCK_MODE_EXTENDED mode. Otherwise, the lock gets released as soon as all your lock obtained callbacks return.

func_start()
{
// code before lock...
cluck::cluck::pointer_t my_lock(std::make_shared<cluck::cluck>(
"my-lock"
, f_messenger
, f_messenger->get_dispatcher()
, cluck::mode_t::CLUCK_MODE_EXTENDED)); // by default mode is SIMPLE
f_communicator->add_connection(my_lock);
my_lock->add_lock_obtained_callback(func_success);
my_lock->add_lock_failed_callback(func_failure);
my_lock->add_finally_callback(func_continue);
my_lock->lock();
// returns to run() loop
}
// on success
bool func_success()
{
// here is the cluster safe code
...code run on success only...
}
// on failure
bool func_failure()
{
...code run on failure only...
}
// after func_success() or func_failure()
bool func_finally()
{
...continue here after the lock was released...
// returns to run() loop
}
std::shared_ptr< cluck > pointer_t
Definition cluck.h:123
bool lock()
Attempt a lock.
Definition cluck.cpp:871
Note
The f_communicator->add_connection() call is what holds the connection. You may also keep a copy of the pointer if necessary. If you need the connection just once, the finally function can be used to remove the connection from the communicator.

The cluck object uses default time out durations. These can be changed using the global functions provided for the purpose. It is also possible to change those values on a per cluck object before calling the lock() function.

The timer is disabled by default. Various functions enable it and set a timeout date to be able to track timeouts locally since we cannot be sure that the cluck service is even running at the time a cluck object tries to communicate with it. Please, do not attempt to use this timer for anything else as it would likely cause issues with this object implementation.

Note
The constructor initializes the timeouts to the special value CLUCK_DEFAULT_TIMEOUT. In that case, the corresponding global durations are used at the time the corresponding timeout is necessary.

The following shows the preparation and demantlement of your client and the successful path of a cluck lock:

msc_inline_mscgraph_1
Note
If you use a simple lock, then the finally_callbacks are called after your client send an UNLOCK but before it received the UNLOCKED message.

The following shows an unsuccessful lock:

msc_inline_mscgraph_2
Parameters
[in]object_nameThe name of the lock.
[in]messengerThe connection used to send messages.
[in]dispatcherThe dispatcher used to receive messages.
[in]modeDefines the usage of the lock.

Definition at line 377 of file cluck.cpp.

References help().

◆ ~cluck()

cluck::cluck::~cluck ( )
overridevirtual

If the lock() command was called, then a set of dispatcher functions were added. The destructor makes sure those get removed in case the finally() function does not get called first.

See also
finally()

Definition at line 413 of file cluck.cpp.

Member Function Documentation

◆ add_finally_callback()

cluck::callback_manager_t::callback_id_t cluck::cluck::add_finally_callback ( callback_t  func,
callback_manager_t::priority_t  priority = callback_manager_t::DEFAULT_PRIORITY 
)

This function adds a callback function to the callback manager used to register function called whenever the object is done with the lock.

Parameters
[in]funcThe callback function to call.
[in]priorityThe priority of the callback.
Returns
The callback identifier.

Definition at line 493 of file cluck.cpp.

◆ add_lock_failed_callback()

cluck::callback_manager_t::callback_id_t cluck::cluck::add_lock_failed_callback ( callback_t  func,
callback_manager_t::priority_t  priority = callback_manager_t::DEFAULT_PRIORITY 
)

This function adds a callback function to the callback manager used to register function called whenever the lock obtention fails.

Parameters
[in]funcThe callback function to call.
[in]priorityThe priority of the callback.
Returns
The callback identifier.

Definition at line 461 of file cluck.cpp.

◆ add_lock_obtained_callback()

cluck::callback_manager_t::callback_id_t cluck::cluck::add_lock_obtained_callback ( callback_t  func,
callback_manager_t::priority_t  priority = callback_manager_t::DEFAULT_PRIORITY 
)

This function adds a callback function to the callback manager used to register function called whenever the lock is obtained.

Parameters
[in]funcThe callback function to call.
[in]priorityThe priority of the callback.
Returns
The callback identifier.

Definition at line 429 of file cluck.cpp.

◆ finally()

void cluck::cluck::finally ( )
protectedvirtual

This function is called once the lock process completes. This means a LOCK was sent and we either were able to do work while the lock was active or the lock failed and we received a call to the lock_failed() function instead.

By default, this function calls all the finally callbacks you added to this object. Make sure to call it if you use callbacks.

Inside the finally() function and callbacks, the state of the lock is "idle". This means you can call the lock() function immediately.

Note
The function makes sure to remove the dispatcher callbacks. This means further events in link with this lock will be ignored. This is considered normal since further events would not make sense at this point.

Definition at line 1348 of file cluck.cpp.

References cluck::CLUCK_STATE_IDLE.

◆ get_lock_duration_timeout()

timeout_t cluck::cluck::get_lock_duration_timeout ( ) const

This function returns the current lock timeout. It can be useful if you want to use a lock with a different timeout and then restore the previous value afterward.

Although if you have access/control of the lock itself, you may instead want to specify the timeout in the snap_lock constructor directly.

Returns
Current lock TTL in seconds.

Definition at line 577 of file cluck.cpp.

◆ get_lock_obtention_timeout()

timeout_t cluck::cluck::get_lock_obtention_timeout ( ) const

This function returns the current timeout for the obtention of a lock. It can be useful if you want to use a lock with a different obtention timeout and then restore the previous value afterward.

Returns
Current lock obtention maximum wait period in microseconds.

Definition at line 523 of file cluck.cpp.

Referenced by lock().

◆ get_mode()

mode_t cluck::cluck::get_mode ( ) const

The lock can be created in various modes. This function returns the mode used when creating the cluck object. This mode cannot be changed once the lock was created.

Returns
The mode the lock was created with.

Definition at line 667 of file cluck.cpp.

◆ get_object_name()

std::string const & cluck::cluck::get_object_name ( ) const

When creating a lock object, you give it a name. This function returns that name.

Returns
The name of this lock object.

Definition at line 653 of file cluck.cpp.

◆ get_reason()

reason_t cluck::cluck::get_reason ( ) const

This function returns the reason of the last failure. Internally, we call the set_reason() to change this value.

Here are the reason for failure:

  • CLUCK_REASON_NONE – no failure detected yet
  • CLUCK_REAON_LOCAL_TIMEOUT – our cluck timer called process_timeout()
  • CLUCK_REAON_REMOTE_TIMEOUT – lock could not be obtained within the obtain lock timeout amount of time alotted
  • CLUCK_REAON_DEADLOCK – the lock would result in a deadlock so it was not attemped; in this case the programmer needs to do some code changes to avoid this situation
Returns
The reason why the lock failed.
See also
set_reason()

Definition at line 744 of file cluck.cpp.

◆ get_timeout_date()

timeout_t cluck::cluck::get_timeout_date ( ) const

This function is used to check when the current lock will be considerd out of date and thus when you should stop doing whatever requires said lock.

You can compare the time against snapdev::now() to know whether the lock timed out. Note that the is_locked() function also technically returns the same information.

snapdev::timespec_ex const now(snapdev::now());
if(lock.get_timeout_date() > now()) // i.e. equivalent to lock.is_locked()
{
// lock still in place -- compute time left
//
snapdev::timespec_ex const time_left(lock.get_timeout_date() - now());
...
}

Remember that this exact date was sent to the cluck service but you may have a clock with a one second or so difference between various computers so if the amount is really small (under 2 seconds) you should probably already considered that the lock has timed out.

Returns
The date when this lock will be over or zero if the lock is not currently active.
See also
lock_timedout()
is_locked()
time_left()

Definition at line 1077 of file cluck.cpp.

◆ get_type()

type_t cluck::cluck::get_type ( ) const

The lock can be given a type changing the behavior of the locking mechanism. Please see the set_type() function for additional details.

Returns
The type of lock this cluck object uses at the moment.
See also
set_type()

Definition at line 682 of file cluck.cpp.

◆ get_unlock_timeout()

timeout_t cluck::cluck::get_unlock_timeout ( ) const

This function returns the current unlock duration. It can be useful if you want to use an unlock with a different timeout and then restore the previous value afterward.

Returns
Current unlock TTL in microseconds.

Definition at line 616 of file cluck.cpp.

◆ help()

bool cluck::cluck::help ( advgetopt::string_set_t &  commands)
private

This function gets called whenever the dispatcher receives the HELP message. It then replies with the COMMANDS message.

The function adds the multiple commands that the cluck supports and which use a non-default match function.

Parameters
[in]commandsThe list of commands to complete.
Returns
Always return true.

Definition at line 781 of file cluck.cpp.

Referenced by cluck().

◆ is_busy()

bool cluck::cluck::is_busy ( ) const

This function checks whether the object is busy. If so, then the lock() function cannot be called. It is expected that the object is and remains busy between the lock() call and the receival of the UNLOCKED message.

Note
This means the object cannot immediately be reused after an unlock(). This is because we need to get the cluck service acknowledgment before we can send a new LOCK message to the cluck service from the same process (TBD: I think that with are serialization we can avoid the UNLOCKING state).
Returns
true if the object is considered busy.

Definition at line 1130 of file cluck.cpp.

References cluck::CLUCK_STATE_IDLE.

◆ is_cluck_msg()

bool cluck::cluck::is_cluck_msg ( ed::message &  msg) const
private

Many of the messages we receive have the exact same set of parameters. This function makes sure that these parameters are valid.

If the object_name or tag are not defined, or if the tag is not a match then this function returns false.

Note
The function expects the "object_name" and "tag" parameters to be defined. These should be tested through the dispatcher with the corresponding message definitions. If this function throws because of a missing parameter, check those message definitions and update them accordingly.
Exceptions
invalid_parameterIf the object_name parameter is not set to this cluck f_object_name value, then this exception is raised. Note that if the object_name parameter or the tag parameters are not defined, the function instead sends an UNKNOWN message reply and then returns false.
Parameters
[in]msgThe message to verify.
Returns
true if the message is considered valid.

Definition at line 1160 of file cluck.cpp.

◆ is_locked()

bool cluck::cluck::is_locked ( ) const

This function checks whether the lock worked and is still considered active, as in, it did not yet time out.

This function does not access the network at all. It checks whether the lock is still valid using the current time and the time at which the LOCKED message said the lock would time out.

If you want to know whether cluck decided that the lock timed out then you need to consider calling the lock_timedout() function instead.

If you want to know how much time you have left on this lock, use the get_timeout_date() instead and subtract time(nullptr). If positive, that's the number of seconds you have left.

Note
The function returns false if there is no lock connection, which means that there is no lock in effect at this time.
Returns
true if the lock is still in effect.
See also
lock_timedout()
get_timeout_date()

Definition at line 1108 of file cluck.cpp.

References cluck::CLUCK_STATE_LOCKED.

◆ lock()

bool cluck::cluck::lock ( )

This function attempts a lock. If a lock was already initiated or is in place, the function fails.

On a timeline, the lock obtention and lock duration parameters are used as follow:

Lock Obtention Fails (timeout)
lock obtention
|<---------------->|
| |
--+------------------+
^ ^
| +--- if lock not obtained, lock_failed() called
+--- send LOCK
Lock Obtention Succeeds -- early release
lock obtention lock duration unlock timeout
|<-----...|<-------------------------------->|<------------>|
| | | |
--+---------+----------------------------------+--------------+-->
^ ^ ^ ^
| | | |
| | | +--- done early, send UNLOCK
| | |
| | +--- do your work safely
| |
| +--- LOCKED received, lock_obtained() called
|
+--- send LOCK
Lock Obtention Succeeds -- late release
lock obtention lock duration unlock timeout
|<-----...|<-------------------------------->|<------------>|
| | | |
--+---------+----------------------------------+--------------+-->
^ ^ ^ ^ ^ ^
| | | | | |
| | | safe work ends here ----+ | |
| | | (client receives UNLOCKING) | |
| | | | |
| | +--- do your work safely | |
| | | |
| | dangerous, but work can end here ----+ |
| | by sending UNLOCK |
| | |
| +--- LOCKED received, lock_obtained() called |
| |
+--- send LOCK too late to do additional work ----+
(client receives UNLOCKED)
virtual void lock_failed()
The lock did not take or an error was reported.
Definition cluck.cpp:1314
virtual void lock_obtained()
This function gets called whenever the lock is in effect.
Definition cluck.cpp:1288
void unlock()
Release the inter-process lock.
Definition cluck.cpp:995

If the lock obtention times out before we receive a LOCKED message back from the cluck service, the process calls your lock_failed() callback functions.

If the LOCKED message is received before the lock obtention times out, then your lock_obtained() callback functions get called.

The cluck service will send an UNLOCKING message once the lock duration is reached and no UNLOCK was received. At that point, continuing work is still safe, but considered dangerous. It is best to try to limit your work so it is complete by the time the lock end date is past.

If the cluck service never receives the UNLOCK message, it ends up sending a UNLOCKED message at the time the "unlock timeout" is reached.

Note
This function does not trigger any calls to your callbacks. These only happen if this function returns true and once replies are received. If the function returns false, then the lock will never happen.
Returns
true if the lock obtention was properly initiated.

Definition at line 871 of file cluck.cpp.

References cluck::CLUCK_DEFAULT_TIMEOUT, cluck::CLUCK_REASON_NONE, cluck::CLUCK_REASON_TRANSMISSION_ERROR, cluck::CLUCK_STATE_FAILED, cluck::CLUCK_STATE_LOCKING, cluck::CLUCK_TYPE_READ_WRITE, get_lock_obtention_timeout(), msg_lock_failed(), msg_locked(), msg_transmission_report(), msg_unlocked(), and msg_unlocking().

◆ lock_failed()

void cluck::cluck::lock_failed ( )
protectedvirtual

When the LOCK message does not get a reply or gets a reply implying that it cannot be secured, this function gets called. You are free to override the function.

By default, this function calls all the lock failed callbacks you added to this object. Make sure to call it if you use callbacks.

See also
add_lock_failed_callback();

Definition at line 1314 of file cluck.cpp.

References cluck::CLUCK_STATE_FAILED.

◆ lock_obtained()

void cluck::cluck::lock_obtained ( )
protectedvirtual

This function is a signal telling you that the lock is in effect. You are free to override it, although, in most likelihood, you'll want to set a lock obtained callback instead.

If you override this function, you are responsible to call this base class version if you want the "lock obtained" callbacks to be called.

Further, the default function checks the cluck lock mode, if SIMPLE, it sends the UNLOCK immediately before returning. In other words, you probably will want to call this instance of the function after you did the work you intended to do while the lock is active.

void my_class::lock_obtained()
{
// ... do work with lock active ...
// call base class function (calls the callbacks)
// ... do additional work after lock was released ...
}
See also
add_lock_obtained_callback()

Definition at line 1288 of file cluck.cpp.

References cluck::CLUCK_MODE_SIMPLE.

◆ msg_lock_failed()

void cluck::cluck::msg_lock_failed ( ed::message &  msg)
private

This function processes the LOCK_FAILED message. This means the state of this cluck object becomes FAILED which means it cannot be used to obtain a lock again.

Parameters
[in]msgThe LOCK_FAILED message.

Definition at line 1398 of file cluck.cpp.

References cluck::CLUCK_REASON_INVALID, and cluck::CLUCK_REASON_REMOTE_TIMEOUT.

Referenced by lock().

◆ msg_locked()

void cluck::cluck::msg_locked ( ed::message &  msg)
private

Whenever the client sends a LOCK message to the cluckd service, it expects a LOCKED reply which means the lock was obtained and is in place for this process to make use of.

The lock_obtained() function is called which in turn calls your lock_obtained callbacks.

Parameters
[in]msgThe LOCKED message.

Definition at line 1367 of file cluck.cpp.

References cluck::CLUCK_REASON_INVALID, and cluck::CLUCK_STATE_LOCKED.

Referenced by lock().

◆ msg_transmission_report()

void cluck::cluck::msg_transmission_report ( ed::message &  msg)
private

If the LOCK message cannot be sent, we receive a transmission error. At the moment, there are two possible reasons:

  • The destination is not currently available and the message was cached
  • The transmission failed because the requested service is not registered

In case of a plain failure, we cancel the whole process immediately.

In case the message was cached, we can ignored the report since the message will eventually make it so it is not an immediate failure. In most cases, if cached, the timeout will let us know if the message does not make it.

Note
At the moment we do not use the cache for any of our messages.
Parameters
[in]msgThe TRANSMISSION_REPORT message.

Definition at line 1450 of file cluck.cpp.

References cluck::CLUCK_REASON_TRANSMISSION_ERROR.

Referenced by lock().

◆ msg_unlocked()

void cluck::cluck::msg_unlocked ( ed::message &  msg)
private

Once the lock of a process is unlocked, the UNLOCKED message is sent to that process. This function processes the acknowledgement which means calling the finally() function.

After this message was received the lock is idle again and can be re-obtained by calling the lock() function.

Parameters
[in]msgThe message sent by the cluck service.

Definition at line 1488 of file cluck.cpp.

References cluck::CLUCK_REASON_INVALID, cluck::CLUCK_REASON_NONE, and cluck::CLUCK_REASON_REMOTE_TIMEOUT.

Referenced by lock().

◆ msg_unlocking()

void cluck::cluck::msg_unlocking ( ed::message &  msg)
private

Whenever the cluck daemon detects that a lock is about to be unlocked, it sends the UNLOCKING message to the lock holder. At that point, the client is expected to stop using the lock. This function actually sends the UNLOCK message to acknowledge receipt of this message.

The client is expected to check the is_locked() function as required to make sure it does not access an unlocked resource.

Parameters
[in]msgThe UNLOCKING message.

Definition at line 1529 of file cluck.cpp.

References cluck::CLUCK_REASON_INVALID, and cluck::CLUCK_REASON_REMOTE_TIMEOUT.

Referenced by lock().

◆ process_timeout()

void cluck::cluck::process_timeout ( )
overridevirtual

This function processes a timeout event. Each time we send a message and require a timely reply, we start a timer to see whether it was indeed timely or not. If not, then this function gets called and we can proceed with canceling the request.

This is often referenced as the local timeout.

Definition at line 1207 of file cluck.cpp.

References cluck::CLUCK_REASON_LOCAL_TIMEOUT, cluck::CLUCK_STATE_FAILED, cluck::CLUCK_STATE_IDLE, cluck::CLUCK_STATE_LOCKED, cluck::CLUCK_STATE_LOCKING, and cluck::CLUCK_STATE_UNLOCKING.

◆ remove_finally_callback()

bool cluck::cluck::remove_finally_callback ( callback_manager_t::callback_id_t  id)

This function is the converse of the add_finally_callback(). If you save the returned callback identifier, you can later call this function to remove the callback explicitly.

Parameters
[in]idThe identifier of the callback to remove.
Returns
true if the callback was indeed removed.

Definition at line 509 of file cluck.cpp.

◆ remove_lock_failed_callback()

bool cluck::cluck::remove_lock_failed_callback ( callback_manager_t::callback_id_t  id)

This function is the converse of the add_lock_failed_callback(). If you save the returned callback identifier, you can later call this function to remove the callback explicitly.

Parameters
[in]idThe identifier of the callback to remove.
Returns
true if the callback was indeed removed.

Definition at line 477 of file cluck.cpp.

◆ remove_lock_obtained_callback()

bool cluck::cluck::remove_lock_obtained_callback ( callback_manager_t::callback_id_t  id)

This function is the converse of the add_lock_obtained_callback(). If you save the returned callback identifier, you can later call this function to remove the callback explicitly.

Parameters
[in]idThe identifier of the callback to remove.
Returns
true if the callback was indeed removed.

Definition at line 445 of file cluck.cpp.

◆ set_lock_duration_timeout()

void cluck::cluck::set_lock_duration_timeout ( timeout_t  timeout)

This function lets you change the default amount of time the inter-process locks last (i.e. their "Time To Live") in seconds.

For example, to keep locks for 1 hour, use 3600.

This value is used whenever a lock is created with its lock duration set to -1.

Parameters
[in]timeoutThe total number of seconds locks will last for by default.

Definition at line 595 of file cluck.cpp.

References cluck::CLUCK_DEFAULT_TIMEOUT, cluck::CLUCK_MAXIMUM_TIMEOUT, and cluck::CLUCK_MINIMUM_TIMEOUT.

◆ set_lock_obtention_timeout()

void cluck::cluck::set_lock_obtention_timeout ( timeout_t  timeout)

This function lets you change the default amount of time the inter-process locks can wait before forfeiting the obtention of a new lock.

This amount can generally remain pretty small. For example, you could say that you want to wait just 1 minute even though the lock you want to get will last 24 hours. This means, within one minute your process is told that the lock cannot be obtained. In other words, you cannot do the work you intended to do. If the lock is released within the 1 minute and you are next on the list, you get the lock and can proceed with the work you intended to do.

The default is five seconds which for a front end is already quite enormous.

Note
Calling this function does not change the timeout connection current duration.
Parameters
[in]timeoutThe number of microseconds to wait to obtain a lock.

Definition at line 553 of file cluck.cpp.

References cluck::CLUCK_DEFAULT_TIMEOUT, cluck::CLUCK_LOCK_OBTENTION_MAXIMUM_TIMEOUT, and cluck::CLUCK_MINIMUM_TIMEOUT.

◆ set_reason()

void cluck::cluck::set_reason ( reason_t  reason)
private

This function saves the reason for the last failure. This can be useful to know how to proceed next. i.e. failure to obtain a lock may tell your application that waiting another 5 minutes before trying again is a possibility.

Note
At the moment, this reason is only used for lock failure, not other potential errors.
Parameters
[in]reasonThe reason why this cluck object failed getting a lock.

Definition at line 763 of file cluck.cpp.

◆ set_type()

void cluck::cluck::set_type ( type_t  type)

This function changes the type of lock the lock() function uses. It can only be called if the cluck object is not currently busy (i.e. before the lock() function is called).

The supported type of locks are:

  • Exclusive Lock (type_t::CLUCK_TYPE_READ_WRITE) – this type of lock can only be obtained by one single process. This is the default.
  • Shared Lock (type_t::CLUCK_TYPE_READ_ONLY) – this type of lock can be obtained by any number of processes. It, however, prevents exclusive locks from taking.
  • Exclusive Lock with Priority (type_t::CLUCK_TYPE_READ_WRITE_PRIORITY) – this is similar to the basic Exclusive Lock, except that it prevents further Shared Locks from happening, making sure that the exclusive lock happens as soon as possible.
Exceptions
busyIf the cluck object is currently in use (trying to obtain a lock, has a lock, releasing a lock) then the busy exception is raised.
Parameters
[in]typeOne of the type_t enumerations.
See also
get_type()

Definition at line 714 of file cluck.cpp.

◆ set_unlock_timeout()

void cluck::cluck::set_unlock_timeout ( timeout_t  timeout)

This function lets you change the default amount of time the inter-process unlock lasts (i.e. their "Time To Survive" after a lock time out) in microseconds.

For example, to allow your application to take up to 5 minutes to acknowledge a timed out lock, set this value to 300'000'000.

Parameters
[in]timeoutThe number of microseconds before timing out on unlock.

Definition at line 633 of file cluck.cpp.

References cluck::CLUCK_DEFAULT_TIMEOUT, cluck::CLUCK_MAXIMUM_TIMEOUT, and cluck::CLUCK_UNLOCK_MINIMUM_TIMEOUT.

◆ unlock()

void cluck::cluck::unlock ( )

This function releases this inter-process lock at the time it gets called. When everything works as expected, this function should be called before the lock times out.

If the lock was not active (i.e. lock() was never called or returned false last time you called it), then nothing happens.

This is useful if you keep the same lock object around and want to lock/unlock it at various time. It is actually very important to unlock your locks so other processes can then gain access to the resources that they protect.

Definition at line 995 of file cluck.cpp.

References cluck::CLUCK_REASON_TRANSMISSION_ERROR, cluck::CLUCK_STATE_FAILED, cluck::CLUCK_STATE_LOCKED, cluck::CLUCK_STATE_LOCKING, and cluck::CLUCK_STATE_UNLOCKING.

Member Data Documentation

◆ f_connection

ed::connection_with_send_message::pointer_t cluck::cluck::f_connection = ed::connection_with_send_message::pointer_t()
private

Definition at line 196 of file cluck.h.

◆ f_dispatcher

ed::dispatcher::pointer_t cluck::cluck::f_dispatcher = ed::dispatcher::pointer_t()
private

Definition at line 197 of file cluck.h.

◆ f_finally_callbacks

callback_manager_t cluck::cluck::f_finally_callbacks = callback_manager_t()
private

Definition at line 201 of file cluck.h.

◆ f_lock_duration_timeout

timeout_t cluck::cluck::f_lock_duration_timeout = CLUCK_DEFAULT_TIMEOUT
private

Definition at line 203 of file cluck.h.

◆ f_lock_failed_callbacks

callback_manager_t cluck::cluck::f_lock_failed_callbacks = callback_manager_t()
private

Definition at line 200 of file cluck.h.

◆ f_lock_obtained_callbacks

callback_manager_t cluck::cluck::f_lock_obtained_callbacks = callback_manager_t()
private

Definition at line 199 of file cluck.h.

◆ f_lock_obtention_timeout

timeout_t cluck::cluck::f_lock_obtention_timeout = CLUCK_DEFAULT_TIMEOUT
private

Definition at line 202 of file cluck.h.

◆ f_lock_timeout_date

timeout_t cluck::cluck::f_lock_timeout_date = timeout_t()
private

Definition at line 205 of file cluck.h.

◆ f_mode

mode_t cluck::cluck::f_mode = mode_t::CLUCK_MODE_SIMPLE
private

Definition at line 198 of file cluck.h.

◆ f_object_name

std::string cluck::cluck::f_object_name = std::string()
private

Definition at line 192 of file cluck.h.

◆ f_reason

reason_t cluck::cluck::f_reason = reason_t::CLUCK_REASON_NONE
private

Definition at line 209 of file cluck.h.

◆ f_serial

serial_t cluck::cluck::f_serial = serial_t()
private

Definition at line 210 of file cluck.h.

◆ f_state

state_t cluck::cluck::f_state = state_t::CLUCK_STATE_IDLE
private

Definition at line 208 of file cluck.h.

◆ f_tag

ed::dispatcher_match::tag_t const cluck::cluck::f_tag = ed::dispatcher_match::DISPATCHER_MATCH_NO_TAG
private

Definition at line 194 of file cluck.h.

◆ f_type

type_t cluck::cluck::f_type = type_t::CLUCK_TYPE_READ_WRITE
private

Definition at line 207 of file cluck.h.

◆ f_unlock_timeout

timeout_t cluck::cluck::f_unlock_timeout = CLUCK_DEFAULT_TIMEOUT
private

Definition at line 204 of file cluck.h.

◆ f_unlocked_timeout_date

timeout_t cluck::cluck::f_unlocked_timeout_date = timeout_t()
private

Definition at line 206 of file cluck.h.


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

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.