Seva Software

 

What is Aruna DB?

Last Updated: 9/25/2001

A_Debug.rb

Purpose

License

Description

Dependencies

Limitations

Performance Considerations

To Do

Usage

Methods

Testing

A_Debug Usage

 

Purpose:

This contains methods that I use to print debug messages when Ruby is run with the -d option. This method is embedded in all of my Ruby code. I use this a lot for debugging my Ruby code. This module adds a few methods to the Thread class that I use to consistently format the thread name. This module contains an extension to the Mutex class call A_Mutex. This extension prints a debug message as the lock is grabbed and released when running with the -d option and allows me to name mutexes. This makes it easy to tell with thread owns each lock and print the locks by name rather than just the id. This is useful for debugging multi-threaded applications. This module adds many new methods to the nil class so that I can operate on variables that are nil with having to constantly check to see if the variable is nil. This is used mostly to make the debug statements easier in that they don't need to check for nil before printing or using the variable. This module adds a new method to all objects called a_show(). This is similar to inspect and allows me to nicely format objects such as strings, arrays, and hashes in debug statements.

 

Description:

Debug messages are printed when running Ruby code with the -d option, such as: ruby -d program_name.rb. You can control the level of debug (or how much debug you see) by calling set_debug_level(#) and changing the debug level. This higher the number the more debug messages you will see. Debug messages are used exactly like print statement except that the message is printed only when debugging (the -d option is used) is turned on.

Changes to the Thread class:

Thread.set_name(thread_name)

This new class method allows me to assign a name to the currently active thread. Debug messages print this name so it is easy for me to tell with thread printed the debug message.

Thread.get_name()

This new class method is called by debug() to print the name of the tread so it is easy for me to tell with thread printed the debug message.

Thread.show_name()

This formats the thread name for printing. I use this when I want to print the thread name. This makes reformatting how the thread name is printed easier (one change instead of many).

a_show(prefix='')

Thread.a_show(prefix='')

This new class method will print the name, status, and any owned locks (locked A_Mutex objects) of each thread. This allows you to quickly see what locks are being held by each Thread. It also prints any threads waiting for a lock. Here is an example from tst_a_btree_thread.rb, there are 8 threads running (t1-t8; t6 owns the read lock, write lock, and not_new_readers lock; t2 and t3 are waiting for the read lock, the 'FileStore-btree_test_fs' lock is used as the btree read lock; t4 and t7 are waiting for the no_new_readers lock, this means they are waiting for t6 to complete it's updates before they can start iterating), main is reported as '?' because the main thread was not named:

Existing Locks used by ArunaDB:

    • gCatalog - global A_Catalog lock used to make sure catalog methods are thread safe. This is only used when A_Catalog's are opened and closed.
    • Catalog-catalog_name
    • gFileStore - global A_FileStore lock used to make sure filestore methods are thread safe. This is only used when A_FileStore's are opened and closed.
    • FileStore-filestore_name - this is used by A_BTree as a read lock. This lock is grabbed whenever a filestore is read from or written to.
    • gBtree - global A_BTtree lock used to make sure btree methods are thread safe. This is only used when A_Btree's are opened and closed.
    • BTree-btee_name-write_lock - the btree_name is being updated. This is used by A_Btree as a write lock.
    • BTree-btree_name - a lock for each btree. If you call A_Btree.lock(), this lock is grabbed.
    • BTree-btree_name-no_new_readers - this lock is only used when the btree keys are not unique. It indicates that this thread has grabbed the no_new_readers lock. This will keep new readers from starting up. The update process can't complete while there are active readers.
    • BTree-waiting_for_readers_to_complete - this lock is only used when the btree keys are not unique. It indicates that this thread is waiting to start iterating because another thread has grabbed the no_new_readers lock.

 

The A_Mutex class:

initialize(name=nil, debug_level=99)

allows you to name the mutex and set the debug level for it's debug messages. The lock() and unlock() use these new parameters.

lock()

Sets @owner = Thread.current and prints a debug statement just after locking the mutex when running with the -d option, here is an example:

unlock()

Clears the @owner and prints a debug statement just before the mutex is unlocked when running with the -d option, here is an example:

 A_Mutex.wait_time

Returns the number of seconds to wait for a lock before raising an error.

A_Mutex.wait_time=

Sets the number of seconds to wait for a lock before raising an error.

 

Changes to the Object class:

a_show() - calls to_s

 

Changes to the Array class:

a_show() - prints the array, for example [1, 2, 'string']

 

Changes to the Hash class:

a_show() - prints the hash, for example: {key => value, key2 => 'string', key2 => [1, 2, 'string']}

 

Changes to the Nil class:

Added many methods to return reasonable data so that nil does not have to be checked. This eliminates the need to check for nil in many cases.

 

Dependencies:

 

Limitations:

  • None

 

Performance Considerations:

 

To Do:

 

Usage:

set_debug_level(29) # set the current debug level.

debug(28, "#{hdr()}this test message #{your class variable} will print only if the program is run with the -d option") if ($DEBUG)

debug(31, "#{hdr()}this test message #{your class variable} will not print because 31 is > 29") if ($DEBUG)

 

Using the guidelines identified in the A_Debug Usage section below:

set_debug_level(19) # will display no btree activity and no filestore activity

set_debug_level(29) # will display all btree activity and no filestore activity

set_debug_level(39) # will display all btree activity and all filestore activity

 

Methods:

set_debug_level(debug_level) - set the current debug level. This has no impact if the -d option is not used when running your program.

debug(#, message) - equivalent to: print "<<#{message}>>\n" if (# <= set_debug_level())

debug_()- exactly like debug() without the leading spaces and trailing "\n", equivalent to: print "<<#{message}>>" if (# <= set_debug_level())

a_hdr() - this will provide a nice formatted header for your debug and raise messages. It prints the thread name, if one has been assigned, the class name, and the @name variable.

Example: debug 24, "#{hdr()}.method_name() - Debug Message" if ($DEBUG)

 

Testing: 

None.

 

A_Debug Usage:

Here are the guidelines I used for ArunaDB:

0-9 - creating/deleting objects

10-19 - database level stuff

20-29 - A_BTree level stuff

30-39 - A_FileStore level stuff

70-80 - A_TempFile and A_FileSort level stuff