genie 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/genie-0.1.gem +0 -0
- data/genie-0.1/docs/classes/BasicCommand.html +249 -0
- data/genie-0.1/docs/classes/BasicCommand.src/M000070.html +18 -0
- data/genie-0.1/docs/classes/BasicCommand.src/M000071.html +18 -0
- data/genie-0.1/docs/classes/BasicCommand.src/M000072.html +18 -0
- data/genie-0.1/docs/classes/BasicCommand.src/M000073.html +18 -0
- data/genie-0.1/docs/classes/BasicCommand.src/M000074.html +16 -0
- data/genie-0.1/docs/classes/Command.html +277 -0
- data/genie-0.1/docs/classes/Command.src/M000052.html +20 -0
- data/genie-0.1/docs/classes/Command.src/M000053.html +18 -0
- data/genie-0.1/docs/classes/Command.src/M000054.html +20 -0
- data/genie-0.1/docs/classes/Command.src/M000055.html +20 -0
- data/genie-0.1/docs/classes/Command.src/M000056.html +18 -0
- data/genie-0.1/docs/classes/Command.src/M000057.html +18 -0
- data/genie-0.1/docs/classes/Command.src/M000058.html +23 -0
- data/genie-0.1/docs/classes/CommandMetainfo.html +362 -0
- data/genie-0.1/docs/classes/CommandMetainfo.src/M000042.html +18 -0
- data/genie-0.1/docs/classes/CommandMetainfo.src/M000043.html +18 -0
- data/genie-0.1/docs/classes/CommandMetainfo.src/M000044.html +19 -0
- data/genie-0.1/docs/classes/CommandMetainfo.src/M000045.html +25 -0
- data/genie-0.1/docs/classes/CommandMetainfo.src/M000046.html +21 -0
- data/genie-0.1/docs/classes/CommandMetainfo.src/M000047.html +21 -0
- data/genie-0.1/docs/classes/CompoundResult.html +359 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000075.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000076.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000078.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000079.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000080.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000082.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000084.html +20 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000085.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000086.html +18 -0
- data/genie-0.1/docs/classes/CompoundResult.src/M000087.html +20 -0
- data/genie-0.1/docs/classes/EntryProcessor.html +223 -0
- data/genie-0.1/docs/classes/EntryProcessor.src/M000008.html +18 -0
- data/genie-0.1/docs/classes/EntryProcessor.src/M000009.html +20 -0
- data/genie-0.1/docs/classes/EntryProcessor.src/M000010.html +18 -0
- data/genie-0.1/docs/classes/EntryProcessor.src/M000011.html +23 -0
- data/genie-0.1/docs/classes/Log4r.html +114 -0
- data/genie-0.1/docs/classes/Log4r/LogEvent.html +153 -0
- data/genie-0.1/docs/classes/Log4r/LogEvent.src/M000123.html +16 -0
- data/genie-0.1/docs/classes/NotifiedProcessor.html +155 -0
- data/genie-0.1/docs/classes/NotifiedProcessor.src/M000094.html +22 -0
- data/genie-0.1/docs/classes/NullTransactionController.html +191 -0
- data/genie-0.1/docs/classes/NullTransactionController.src/M000030.html +16 -0
- data/genie-0.1/docs/classes/NullTransactionController.src/M000031.html +16 -0
- data/genie-0.1/docs/classes/Object.html +154 -0
- data/genie-0.1/docs/classes/Object.src/M000103.html +16 -0
- data/genie-0.1/docs/classes/Periodic.html +564 -0
- data/genie-0.1/docs/classes/Periodic.src/M000124.html +26 -0
- data/genie-0.1/docs/classes/Periodic.src/M000125.html +21 -0
- data/genie-0.1/docs/classes/Periodic.src/M000126.html +18 -0
- data/genie-0.1/docs/classes/Periodic.src/M000127.html +18 -0
- data/genie-0.1/docs/classes/Periodic.src/M000128.html +31 -0
- data/genie-0.1/docs/classes/Periodic.src/M000129.html +30 -0
- data/genie-0.1/docs/classes/Periodic.src/M000130.html +18 -0
- data/genie-0.1/docs/classes/Periodic.src/M000131.html +18 -0
- data/genie-0.1/docs/classes/Periodic.src/M000132.html +16 -0
- data/genie-0.1/docs/classes/PollingProcessor.html +303 -0
- data/genie-0.1/docs/classes/PollingProcessor.src/M000088.html +23 -0
- data/genie-0.1/docs/classes/PollingProcessor.src/M000089.html +19 -0
- data/genie-0.1/docs/classes/PollingProcessor.src/M000091.html +22 -0
- data/genie-0.1/docs/classes/PollingProcessor.src/M000092.html +18 -0
- data/genie-0.1/docs/classes/PollingProcessor.src/M000093.html +18 -0
- data/genie-0.1/docs/classes/Queue.html +562 -0
- data/genie-0.1/docs/classes/Queue.src/M000104.html +22 -0
- data/genie-0.1/docs/classes/Queue.src/M000105.html +18 -0
- data/genie-0.1/docs/classes/Queue.src/M000106.html +18 -0
- data/genie-0.1/docs/classes/Queue.src/M000107.html +18 -0
- data/genie-0.1/docs/classes/Queue.src/M000108.html +21 -0
- data/genie-0.1/docs/classes/Queue.src/M000109.html +21 -0
- data/genie-0.1/docs/classes/Queue.src/M000110.html +22 -0
- data/genie-0.1/docs/classes/Queue.src/M000111.html +16 -0
- data/genie-0.1/docs/classes/Queue.src/M000112.html +18 -0
- data/genie-0.1/docs/classes/Queue.src/M000113.html +19 -0
- data/genie-0.1/docs/classes/Queue.src/M000114.html +23 -0
- data/genie-0.1/docs/classes/Queue.src/M000115.html +21 -0
- data/genie-0.1/docs/classes/Queue.src/M000116.html +19 -0
- data/genie-0.1/docs/classes/Queue.src/M000117.html +20 -0
- data/genie-0.1/docs/classes/Queue.src/M000118.html +25 -0
- data/genie-0.1/docs/classes/Queue.src/M000119.html +18 -0
- data/genie-0.1/docs/classes/Queue.src/M000120.html +22 -0
- data/genie-0.1/docs/classes/Queue.src/M000121.html +22 -0
- data/genie-0.1/docs/classes/Queue.src/M000122.html +20 -0
- data/genie-0.1/docs/classes/QueueDispatcher.html +247 -0
- data/genie-0.1/docs/classes/QueueDispatcher.src/M000048.html +18 -0
- data/genie-0.1/docs/classes/QueueDispatcher.src/M000049.html +21 -0
- data/genie-0.1/docs/classes/QueueDispatcher.src/M000050.html +18 -0
- data/genie-0.1/docs/classes/QueueDispatcher.src/M000051.html +32 -0
- data/genie-0.1/docs/classes/QueueEntry.html +522 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000012.html +21 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000013.html +18 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000014.html +18 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000015.html +18 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000017.html +16 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000018.html +19 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000020.html +19 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000022.html +19 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000023.html +21 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000024.html +19 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000025.html +18 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000026.html +18 -0
- data/genie-0.1/docs/classes/QueueEntry.src/M000028.html +18 -0
- data/genie-0.1/docs/classes/Result.html +289 -0
- data/genie-0.1/docs/classes/Result.src/M000063.html +20 -0
- data/genie-0.1/docs/classes/Result.src/M000064.html +18 -0
- data/genie-0.1/docs/classes/Result.src/M000066.html +18 -0
- data/genie-0.1/docs/classes/Result.src/M000068.html +18 -0
- data/genie-0.1/docs/classes/Result.src/M000069.html +19 -0
- data/genie-0.1/docs/classes/SemanticCommand.html +229 -0
- data/genie-0.1/docs/classes/SemanticCommand.src/M000059.html +19 -0
- data/genie-0.1/docs/classes/SemanticCommand.src/M000060.html +18 -0
- data/genie-0.1/docs/classes/SemanticCommand.src/M000061.html +18 -0
- data/genie-0.1/docs/classes/TransactionBundle.html +260 -0
- data/genie-0.1/docs/classes/TransactionBundle.src/M000001.html +18 -0
- data/genie-0.1/docs/classes/TransactionBundle.src/M000002.html +20 -0
- data/genie-0.1/docs/classes/TransactionBundle.src/M000003.html +20 -0
- data/genie-0.1/docs/classes/TransactionBundle.src/M000004.html +18 -0
- data/genie-0.1/docs/classes/TransactionBundle.src/M000005.html +18 -0
- data/genie-0.1/docs/classes/TransactionBundle.src/M000007.html +19 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.html +308 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000095.html +19 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000096.html +16 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000097.html +16 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000098.html +16 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000099.html +18 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000101.html +18 -0
- data/genie-0.1/docs/classes/UndoRedoCommand.src/M000102.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.html +322 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000032.html +19 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000033.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000034.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000035.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000036.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000037.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000038.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000039.html +18 -0
- data/genie-0.1/docs/classes/UnitOfWork.src/M000040.html +18 -0
- data/genie-0.1/docs/created.rid +1 -0
- data/genie-0.1/docs/dot/f_0.dot +14 -0
- data/genie-0.1/docs/dot/f_0.png +0 -0
- data/genie-0.1/docs/dot/f_1.dot +14 -0
- data/genie-0.1/docs/dot/f_1.png +0 -0
- data/genie-0.1/docs/dot/f_2.dot +14 -0
- data/genie-0.1/docs/dot/f_2.png +0 -0
- data/genie-0.1/docs/dot/f_3.dot +84 -0
- data/genie-0.1/docs/dot/f_3.png +0 -0
- data/genie-0.1/docs/dot/f_4.dot +14 -0
- data/genie-0.1/docs/dot/f_4.png +0 -0
- data/genie-0.1/docs/dot/f_5.dot +78 -0
- data/genie-0.1/docs/dot/f_5.png +0 -0
- data/genie-0.1/docs/dot/f_6.dot +50 -0
- data/genie-0.1/docs/dot/f_6.png +0 -0
- data/genie-0.1/docs/dot/f_7.dot +57 -0
- data/genie-0.1/docs/dot/f_7.png +0 -0
- data/genie-0.1/docs/dot/m_5_0.dot +30 -0
- data/genie-0.1/docs/dot/m_5_0.png +0 -0
- data/genie-0.1/docs/dot/m_7_0.dot +39 -0
- data/genie-0.1/docs/dot/m_7_0.png +0 -0
- data/genie-0.1/docs/files/License_txt.html +161 -0
- data/genie-0.1/docs/files/ReadMe_Amber_txt.html +491 -0
- data/genie-0.1/docs/files/ReadMe_txt.html +444 -0
- data/genie-0.1/docs/files/nist/genie/commands_rb.html +121 -0
- data/genie-0.1/docs/files/nist/genie/genie_rb.html +116 -0
- data/genie-0.1/docs/files/nist/genie/processors_rb.html +111 -0
- data/genie-0.1/docs/files/nist/genie/queues_rb.html +118 -0
- data/genie-0.1/docs/files/nist/genie/results_rb.html +117 -0
- data/genie-0.1/docs/fr_class_index.html +46 -0
- data/genie-0.1/docs/fr_file_index.html +34 -0
- data/genie-0.1/docs/fr_method_index.html +160 -0
- data/genie-0.1/docs/images/overview.jpg +0 -0
- data/genie-0.1/docs/index.html +24 -0
- data/genie-0.1/docs/rdoc-style.css +208 -0
- data/genie-0.1/lib/nist/genie/commands.rb +413 -0
- data/genie-0.1/lib/nist/genie/genie.rb +4 -0
- data/genie-0.1/lib/nist/genie/processors.rb +382 -0
- data/genie-0.1/lib/nist/genie/queues.rb +435 -0
- data/genie-0.1/lib/nist/genie/results.rb +113 -0
- data/genie-0.1/tests/helpers.rb +45 -0
- data/genie-0.1/tests/test_commands.rb +338 -0
- data/genie-0.1/tests/test_processors.rb +17 -0
- data/genie-0.1/tests/test_queues.rb +288 -0
- data/genie-0.1/tests/test_results.rb +37 -0
- data/trimurti-0.1.gem +0 -0
- data/trimurti-0.1/docs/classes/Array.html +176 -0
- data/trimurti-0.1/docs/classes/Array.src/M000005.html +19 -0
- data/trimurti-0.1/docs/classes/Array.src/M000006.html +19 -0
- data/trimurti-0.1/docs/classes/Asserter.html +136 -0
- data/trimurti-0.1/docs/classes/Brahma.html +360 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000029.html +21 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000030.html +20 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000031.html +36 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000032.html +18 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000033.html +20 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000034.html +21 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000035.html +25 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000036.html +22 -0
- data/trimurti-0.1/docs/classes/Brahma.src/M000037.html +22 -0
- data/trimurti-0.1/docs/classes/ComponentSpec.html +275 -0
- data/trimurti-0.1/docs/classes/ComponentSpec.src/M000001.html +21 -0
- data/trimurti-0.1/docs/classes/ComponentSpec.src/M000002.html +18 -0
- data/trimurti-0.1/docs/classes/DRb.html +165 -0
- data/trimurti-0.1/docs/classes/DRb.src/M000062.html +18 -0
- data/trimurti-0.1/docs/classes/DRb.src/M000063.html +18 -0
- data/trimurti-0.1/docs/classes/GUID.html +129 -0
- data/trimurti-0.1/docs/classes/Linda.html +444 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000007.html +16 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000008.html +16 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000009.html +20 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000010.html +16 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000011.html +18 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000012.html +21 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000013.html +18 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000014.html +18 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000015.html +18 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000016.html +18 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000017.html +20 -0
- data/trimurti-0.1/docs/classes/Linda.src/M000018.html +20 -0
- data/trimurti-0.1/docs/classes/Object.html +153 -0
- data/trimurti-0.1/docs/classes/Object.src/M000021.html +18 -0
- data/trimurti-0.1/docs/classes/Plugins.html +174 -0
- data/trimurti-0.1/docs/classes/Plugins.src/M000024.html +32 -0
- data/trimurti-0.1/docs/classes/Plugins.src/M000025.html +32 -0
- data/trimurti-0.1/docs/classes/Plugins/Spec.html +267 -0
- data/trimurti-0.1/docs/classes/Plugins/Spec.src/M000026.html +22 -0
- data/trimurti-0.1/docs/classes/Plugins/Spec.src/M000027.html +18 -0
- data/trimurti-0.1/docs/classes/Plugins/Spec.src/M000028.html +20 -0
- data/trimurti-0.1/docs/classes/QBE_ID.html +147 -0
- data/trimurti-0.1/docs/classes/QBE_ID.src/M000059.html +18 -0
- data/trimurti-0.1/docs/classes/QueryByExample.html +270 -0
- data/trimurti-0.1/docs/classes/QueryByExample.src/M000054.html +17 -0
- data/trimurti-0.1/docs/classes/QueryByExample.src/M000055.html +17 -0
- data/trimurti-0.1/docs/classes/QueryByExample.src/M000056.html +17 -0
- data/trimurti-0.1/docs/classes/QueryByExample.src/M000057.html +17 -0
- data/trimurti-0.1/docs/classes/QueryByExample.src/M000058.html +17 -0
- data/trimurti-0.1/docs/classes/Shiva.html +159 -0
- data/trimurti-0.1/docs/classes/Shiva.src/M000060.html +18 -0
- data/trimurti-0.1/docs/classes/Shiva.src/M000061.html +19 -0
- data/trimurti-0.1/docs/classes/String.html +176 -0
- data/trimurti-0.1/docs/classes/String.src/M000022.html +16 -0
- data/trimurti-0.1/docs/classes/String.src/M000023.html +16 -0
- data/trimurti-0.1/docs/classes/Symbol.html +176 -0
- data/trimurti-0.1/docs/classes/Symbol.src/M000003.html +16 -0
- data/trimurti-0.1/docs/classes/Symbol.src/M000004.html +16 -0
- data/trimurti-0.1/docs/classes/Trimurti.html +189 -0
- data/trimurti-0.1/docs/classes/Trimurti.src/M000019.html +16 -0
- data/trimurti-0.1/docs/classes/Trimurti.src/M000020.html +16 -0
- data/trimurti-0.1/docs/classes/Vishnu.html +563 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000038.html +18 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000039.html +18 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000040.html +18 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000041.html +22 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000042.html +23 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000043.html +24 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000044.html +24 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000045.html +18 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000046.html +22 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000047.html +20 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000048.html +18 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000049.html +22 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000050.html +20 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000051.html +19 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000052.html +30 -0
- data/trimurti-0.1/docs/classes/Vishnu.src/M000053.html +21 -0
- data/trimurti-0.1/docs/created.rid +1 -0
- data/trimurti-0.1/docs/dot/f_0.dot +14 -0
- data/trimurti-0.1/docs/dot/f_0.png +0 -0
- data/trimurti-0.1/docs/dot/f_1.dot +14 -0
- data/trimurti-0.1/docs/dot/f_1.png +0 -0
- data/trimurti-0.1/docs/dot/f_2.dot +14 -0
- data/trimurti-0.1/docs/dot/f_2.png +0 -0
- data/trimurti-0.1/docs/dot/f_3.dot +39 -0
- data/trimurti-0.1/docs/dot/f_3.png +0 -0
- data/trimurti-0.1/docs/dot/f_4.dot +39 -0
- data/trimurti-0.1/docs/dot/f_4.png +0 -0
- data/trimurti-0.1/docs/dot/f_5.dot +69 -0
- data/trimurti-0.1/docs/dot/f_5.png +0 -0
- data/trimurti-0.1/docs/dot/f_6.dot +149 -0
- data/trimurti-0.1/docs/dot/f_6.png +0 -0
- data/trimurti-0.1/docs/dot/m_3_0.dot +30 -0
- data/trimurti-0.1/docs/dot/m_3_0.png +0 -0
- data/trimurti-0.1/docs/dot/m_4_0.dot +39 -0
- data/trimurti-0.1/docs/dot/m_4_0.png +0 -0
- data/trimurti-0.1/docs/dot/m_5_0.dot +40 -0
- data/trimurti-0.1/docs/dot/m_5_0.png +0 -0
- data/trimurti-0.1/docs/dot/m_5_1.dot +30 -0
- data/trimurti-0.1/docs/dot/m_5_1.png +0 -0
- data/trimurti-0.1/docs/dot/m_6_0.dot +40 -0
- data/trimurti-0.1/docs/dot/m_6_0.png +0 -0
- data/trimurti-0.1/docs/dot/m_6_1.dot +30 -0
- data/trimurti-0.1/docs/dot/m_6_1.png +0 -0
- data/trimurti-0.1/docs/dot/m_6_2.dot +30 -0
- data/trimurti-0.1/docs/dot/m_6_2.png +0 -0
- data/trimurti-0.1/docs/files/License_txt.html +132 -0
- data/trimurti-0.1/docs/files/ReadMe_Amber_txt.html +491 -0
- data/trimurti-0.1/docs/files/ReadMe_txt.html +694 -0
- data/trimurti-0.1/docs/files/nist/trimurti/linda_rb.html +129 -0
- data/trimurti-0.1/docs/files/nist/trimurti/plugins_rb.html +129 -0
- data/trimurti-0.1/docs/files/nist/trimurti/queryByExample_rb.html +128 -0
- data/trimurti-0.1/docs/files/nist/trimurti/trimurti_rb.html +151 -0
- data/trimurti-0.1/docs/fr_class_index.html +43 -0
- data/trimurti-0.1/docs/fr_file_index.html +33 -0
- data/trimurti-0.1/docs/fr_method_index.html +89 -0
- data/trimurti-0.1/docs/images/overview.jpg +0 -0
- data/trimurti-0.1/docs/index.html +24 -0
- data/trimurti-0.1/docs/rdoc-style.css +208 -0
- data/trimurti-0.1/lib/nist/trimurti/linda.rb +163 -0
- data/trimurti-0.1/lib/nist/trimurti/plugins.rb +107 -0
- data/trimurti-0.1/lib/nist/trimurti/queryByExample.rb +81 -0
- data/trimurti-0.1/lib/nist/trimurti/trimurti.rb +433 -0
- data/trimurti-0.1/tests/test_linda.rb +111 -0
- data/trimurti-0.1/tests/test_trimurti.rb +247 -0
- metadata +467 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
|
|
2
|
+
require 'nist/common/guid'
|
|
3
|
+
require 'nist/common/log'
|
|
4
|
+
require 'nist/common/singletonReflection'
|
|
5
|
+
|
|
6
|
+
Object.outputters << Log4r::ObjectOutputter.new('CommandNotification')
|
|
7
|
+
|
|
8
|
+
# ==============================================
|
|
9
|
+
|
|
10
|
+
class Object
|
|
11
|
+
|
|
12
|
+
def resolve; self; end
|
|
13
|
+
|
|
14
|
+
end # Object
|
|
15
|
+
|
|
16
|
+
# ==============================================
|
|
17
|
+
|
|
18
|
+
# In addition to specifying some information about
|
|
19
|
+
# the commands associated with a particular semantic,
|
|
20
|
+
# instances contain Procs that tell the command how
|
|
21
|
+
# to 'do' and 'undo'. The default behavior is to
|
|
22
|
+
# send do_<semantics> or undo_<semantics> to the target.
|
|
23
|
+
class CommandMetainfo
|
|
24
|
+
|
|
25
|
+
@@registry = Hash.new
|
|
26
|
+
|
|
27
|
+
# Look up an instance.
|
|
28
|
+
def self.[](sym)
|
|
29
|
+
@@registry[sym]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Look up an instance: identical to [].
|
|
33
|
+
def self.lookup(sym)
|
|
34
|
+
self[sym]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# The Symbol that identifies the command semantics.
|
|
38
|
+
attr_reader :semantics
|
|
39
|
+
|
|
40
|
+
# A string that a GUI can use to explain the command.
|
|
41
|
+
# Defaults to a String representation of the semantics.
|
|
42
|
+
attr_accessor :description
|
|
43
|
+
|
|
44
|
+
# An Integer (defaults to one).
|
|
45
|
+
attr_accessor :max_attempts
|
|
46
|
+
|
|
47
|
+
# A Boolean, true if the command might change
|
|
48
|
+
# data. If this is false, the command is
|
|
49
|
+
# guaranteed not to change any data: it is
|
|
50
|
+
# only a query.
|
|
51
|
+
attr_accessor :may_update
|
|
52
|
+
|
|
53
|
+
# A Boolean, true if the command has more complicated
|
|
54
|
+
# effects than a setter: defaults to true
|
|
55
|
+
attr_accessor :may_have_side_effects
|
|
56
|
+
|
|
57
|
+
# A Float that guesses how long the operation might
|
|
58
|
+
# take. It would be more accurate (but a nuisance)
|
|
59
|
+
# to maintain separate estimates for do and undo.
|
|
60
|
+
# The larger of the two is probably the best to use.
|
|
61
|
+
# For that matter, it would be nice to have separate
|
|
62
|
+
# estimates for CPU time and wall clock time.
|
|
63
|
+
# This value is not automatically maintaind: some
|
|
64
|
+
# separate process needs to periodically update
|
|
65
|
+
# this, based on the result's execution_seconds.
|
|
66
|
+
attr_accessor :estimated_seconds
|
|
67
|
+
|
|
68
|
+
# A Proc which takes arguments:
|
|
69
|
+
# 1. Target
|
|
70
|
+
# 2. Semantics
|
|
71
|
+
# 3. Argument Hash (should not be modified)
|
|
72
|
+
# 4. Undo data Hash (may have extra data added)
|
|
73
|
+
attr_accessor :do_proc
|
|
74
|
+
|
|
75
|
+
# An optional Proc which takes arguments:
|
|
76
|
+
# 1. Target
|
|
77
|
+
# 2. Semantics
|
|
78
|
+
# 3. Argument Hash (should not be modified. Includes undo data.)
|
|
79
|
+
# If the undo_proc is nil, the command can not be undone.
|
|
80
|
+
attr_accessor :undo_proc
|
|
81
|
+
|
|
82
|
+
# Sets the description as well as the semantics.
|
|
83
|
+
def semantics=(aSymbol)
|
|
84
|
+
@semantics=aSymbol
|
|
85
|
+
self.description=aSymbol.to_s
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# New instances are automatically cached in the @@registry.
|
|
89
|
+
def initialize(semantics)
|
|
90
|
+
self.semantics=semantics
|
|
91
|
+
@@registry[semantics]=self
|
|
92
|
+
self.max_attempts=1
|
|
93
|
+
self.estimated_seconds=0.1
|
|
94
|
+
self.may_update=true
|
|
95
|
+
self.may_have_side_effects=true
|
|
96
|
+
self.do_proc=default_do_proc
|
|
97
|
+
self.undo_proc=default_undo_proc
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns the do_proc that gets used if you do not provide another.
|
|
101
|
+
def default_do_proc
|
|
102
|
+
lambda {|target, method_name, argHash, undoDataHash|
|
|
103
|
+
method_name = 'do_'+semantics.to_s
|
|
104
|
+
target.send(method_name, argHash, undoDataHash)
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Returns the undo_proc that gets used if you do not provide another.
|
|
109
|
+
def default_undo_proc
|
|
110
|
+
lambda {|target, semantics, argHash|
|
|
111
|
+
method_name = 'undo_'+semantics.to_s
|
|
112
|
+
target.send(method_name, argHash)
|
|
113
|
+
}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end # CommandMetainfo
|
|
117
|
+
|
|
118
|
+
# ==============================================
|
|
119
|
+
|
|
120
|
+
# An abstract factor. Has an invariant command_id,
|
|
121
|
+
# can wrap itself in a QueueEntry, and can
|
|
122
|
+
# make its inverse.
|
|
123
|
+
class BasicCommand
|
|
124
|
+
|
|
125
|
+
# Uniquely identifies this instance.
|
|
126
|
+
attr_reader :command_id
|
|
127
|
+
|
|
128
|
+
def initialize
|
|
129
|
+
@command_id=GUID.new
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def to_entry
|
|
133
|
+
QueueEntry.new(self)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Returns a command that undoes the receiver.
|
|
137
|
+
def inverse
|
|
138
|
+
UndoRedoCommand.new(self)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Returns the chain of do/undo/redo actions
|
|
142
|
+
# culminating in the receiver. For most commands
|
|
143
|
+
# this returns an Array containing only the
|
|
144
|
+
# receiver. UndoRedoCommand instances return
|
|
145
|
+
# Arrays that have more than one element.
|
|
146
|
+
def command_chain
|
|
147
|
+
[self]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Returns one of three Symbols (:do, :undo, :redo)
|
|
151
|
+
# depending on the function of the 'do' message.
|
|
152
|
+
# For most commands, this returns :do. Only
|
|
153
|
+
# UndoRedoCommands can return :undo or :redo.
|
|
154
|
+
def type; :do; end
|
|
155
|
+
|
|
156
|
+
end # BasicCommand
|
|
157
|
+
|
|
158
|
+
# ==============================================
|
|
159
|
+
|
|
160
|
+
# An abstract factor. Knows its semantics, and
|
|
161
|
+
# can use that knowlege to look up a CommandMetainfo
|
|
162
|
+
# (which answers several queries on behalf of the command).
|
|
163
|
+
class SemanticCommand < BasicCommand
|
|
164
|
+
|
|
165
|
+
# A Symbol that specifies what the command does
|
|
166
|
+
attr_accessor :semantics
|
|
167
|
+
|
|
168
|
+
def initialize(semantics)
|
|
169
|
+
self.semantics=semantics
|
|
170
|
+
super()
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Returns the CommandMetainfo that describes the receiver.
|
|
174
|
+
def metainfo
|
|
175
|
+
CommandMetainfo[semantics]
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Returns a Boolean, true if the command can be undone
|
|
179
|
+
# (because the metainfo posesses an undo_proc).
|
|
180
|
+
# Compare to QueueDispatcher#undo?
|
|
181
|
+
def undoable?
|
|
182
|
+
!metainfo.undo_proc.nil?
|
|
183
|
+
end
|
|
184
|
+
alias is_undoable undoable?
|
|
185
|
+
|
|
186
|
+
forward(:metainfo, CommandMetainfo, :max_attempts, :may_update, :may_have_side_effects, :estimated_seconds, :description)
|
|
187
|
+
|
|
188
|
+
end # SemanticCommand
|
|
189
|
+
|
|
190
|
+
# ==============================================
|
|
191
|
+
|
|
192
|
+
# Represents a basic operation. This implementation
|
|
193
|
+
# relies command description in the form of a CommandMetainfo
|
|
194
|
+
# that has semantics corresponding to the Command.
|
|
195
|
+
class Command < SemanticCommand
|
|
196
|
+
|
|
197
|
+
attr_accessor :target
|
|
198
|
+
|
|
199
|
+
attr_accessor :args
|
|
200
|
+
|
|
201
|
+
attr_accessor :undo_data
|
|
202
|
+
|
|
203
|
+
def initialize(semantics)
|
|
204
|
+
self.args=Hash.new
|
|
205
|
+
self.undo_data=Hash.new
|
|
206
|
+
super
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def target_resolved
|
|
210
|
+
target.resolve
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def args_resolved
|
|
214
|
+
answer = Hash.new
|
|
215
|
+
args.each {|key, value| answer[key]=value.resolve }
|
|
216
|
+
answer
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Returns a resolved Hash that includes
|
|
220
|
+
# undo_data as well as args.
|
|
221
|
+
def data_resolved
|
|
222
|
+
answer = args_resolved
|
|
223
|
+
undo_data.each {|key, value| answer[key]=value.resolve }
|
|
224
|
+
answer
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Builds a Result by executing a block with error handling and logging.
|
|
228
|
+
# FIXME: Logging needs to be per-thread, since several processors
|
|
229
|
+
# might be working in parallel.
|
|
230
|
+
def _execute(method)
|
|
231
|
+
answer = Result.new
|
|
232
|
+
notices = Log4r::Outputter['CommandNotification'].history
|
|
233
|
+
notices.clear
|
|
234
|
+
startTime = Time.now
|
|
235
|
+
begin
|
|
236
|
+
answer.result = yield
|
|
237
|
+
rescue LoggedFatal
|
|
238
|
+
# Do nothing, it's already logged
|
|
239
|
+
rescue Exception => e
|
|
240
|
+
# Log the exception (without throwing a new LoggedFatal)
|
|
241
|
+
cr = "\n\t"
|
|
242
|
+
self.logger.fatal("Command::#{method} caught exception of class #{e.class.name} with message <#{e.message}> and backtrace #{cr}<#{e.backtrace.join(cr)}>.")
|
|
243
|
+
end
|
|
244
|
+
answer.execution_seconds = Time.now - startTime
|
|
245
|
+
answer.add_notices(notices)
|
|
246
|
+
answer
|
|
247
|
+
end
|
|
248
|
+
private :_execute
|
|
249
|
+
|
|
250
|
+
def _do(cache_undo_data)
|
|
251
|
+
ud = cache_undo_data ? undo_data : Hash.new
|
|
252
|
+
answer = _execute('do') {metainfo.do_proc.call(target_resolved, semantics, args_resolved, ud)}
|
|
253
|
+
answer.undo_data=ud
|
|
254
|
+
answer
|
|
255
|
+
end
|
|
256
|
+
private :_do
|
|
257
|
+
|
|
258
|
+
def do()
|
|
259
|
+
_do(true)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def redo
|
|
263
|
+
_do(false)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def undo
|
|
267
|
+
if undoable?
|
|
268
|
+
return _execute('undo') {metainfo.undo_proc.call(target_resolved, semantics, data_resolved)}
|
|
269
|
+
end
|
|
270
|
+
answer = Result.new
|
|
271
|
+
answer.add_error("Attempt to undo a command (semantics=:#{semantics.to_s}) which is not undoable.")
|
|
272
|
+
answer
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
end # Command
|
|
277
|
+
|
|
278
|
+
# ==============================================
|
|
279
|
+
|
|
280
|
+
# Represents an indivisible collection of Commands
|
|
281
|
+
# that succeed or fail or as unit. Some metainformation
|
|
282
|
+
# (such as max_attempts) comes from the semantics-specified
|
|
283
|
+
# CommandMetainfo, but others (such as may_update and
|
|
284
|
+
# may_have_side_effects) are derived from the children.
|
|
285
|
+
# This is the safest thing to do. In principle one could
|
|
286
|
+
# implement a process which ensures that the CommandMetainfo
|
|
287
|
+
# is fully consistent with the chilren for all reasonable
|
|
288
|
+
# combinations of children, but that would probably be
|
|
289
|
+
# error prone.
|
|
290
|
+
class UnitOfWork < SemanticCommand
|
|
291
|
+
|
|
292
|
+
# An Array of component Commands.
|
|
293
|
+
attr_accessor :children
|
|
294
|
+
|
|
295
|
+
def initialize(semantics, *kids)
|
|
296
|
+
self.children=kids
|
|
297
|
+
super(semantics)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def size
|
|
301
|
+
children.size
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def [](idx)
|
|
305
|
+
children[idx]
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# which_method is either :do, :redo, or :undo
|
|
309
|
+
def _do(which_method)
|
|
310
|
+
answer = CompoundResult.new
|
|
311
|
+
children.each {|kid|
|
|
312
|
+
r = kid.send(which_method)
|
|
313
|
+
answer << r
|
|
314
|
+
break if r.error?
|
|
315
|
+
}
|
|
316
|
+
answer
|
|
317
|
+
end
|
|
318
|
+
private :_do
|
|
319
|
+
|
|
320
|
+
def do()
|
|
321
|
+
_do(:do)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def redo()
|
|
325
|
+
_do(:redo)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def undo()
|
|
329
|
+
_do(:undo)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def may_update
|
|
334
|
+
children.any? {|kid| kid.may_update }
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def may_have_side_effects
|
|
338
|
+
children.any? {|kid| kid.may_have_side_effects }
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Returns a Boolean, true if the command can be undone
|
|
342
|
+
# (because the metainfo posesses an undo_proc).
|
|
343
|
+
# Compare to QueueDispatcher#undo?
|
|
344
|
+
def undoable?
|
|
345
|
+
children.all? {|kid| kid.undoable? }
|
|
346
|
+
end
|
|
347
|
+
alias is_undoable undoable?
|
|
348
|
+
|
|
349
|
+
end # UnitOfWork
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
# ==============================================
|
|
353
|
+
|
|
354
|
+
# Represents a command that undoes some other command.
|
|
355
|
+
# A redo is an undo of an undo.
|
|
356
|
+
class UndoRedoCommand < BasicCommand
|
|
357
|
+
|
|
358
|
+
# The command that gets undone (not the command at the end
|
|
359
|
+
# of the chain)
|
|
360
|
+
attr_accessor :command_undone
|
|
361
|
+
|
|
362
|
+
# The id of the command that gets undone. Used for marshalling.
|
|
363
|
+
attr_accessor :id_of_command_undone
|
|
364
|
+
|
|
365
|
+
def initialize(command)
|
|
366
|
+
self.command_undone=command
|
|
367
|
+
self.id_of_command_undone=command.command_id
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
forward(:command_undone, Command, :max_attempts, :may_update, :may_have_side_effects, :description)
|
|
371
|
+
|
|
372
|
+
def do(); command_undone.undo; end
|
|
373
|
+
|
|
374
|
+
def redo; self.do(); end
|
|
375
|
+
|
|
376
|
+
def undo; command_undone.redo; end
|
|
377
|
+
|
|
378
|
+
# Returns a Boolean, true if the command can be undone
|
|
379
|
+
# (because the metainfo posesses an undo_proc).
|
|
380
|
+
# Compare to QueueDispatcher#undo?
|
|
381
|
+
# This method always returns true, under the
|
|
382
|
+
# presumption that instance creation was valid.
|
|
383
|
+
# The first UndoRedoCommand in an undo/redo chain
|
|
384
|
+
# should be created only if the base command is
|
|
385
|
+
# undoable. Undoing the UndoRedoCommand is equivalent
|
|
386
|
+
# to a redo of the original command, so that is always
|
|
387
|
+
# possible.
|
|
388
|
+
def undoable?
|
|
389
|
+
true
|
|
390
|
+
end
|
|
391
|
+
alias is_undoable undoable?
|
|
392
|
+
|
|
393
|
+
# Returns the chain of do/undo/redo actions
|
|
394
|
+
# culminating in the receiver.
|
|
395
|
+
# UndoRedoCommand instances return
|
|
396
|
+
# Arrays that have more than one element.
|
|
397
|
+
# Other commands returns an Array containing
|
|
398
|
+
# only the receiver.
|
|
399
|
+
def command_chain
|
|
400
|
+
command_undone.command_chain << self
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Returns one of three Symbols (:do, :undo, :redo)
|
|
404
|
+
# depending on the function of the 'do' message.
|
|
405
|
+
# UndoRedoCommands can only return :undo or :redo.
|
|
406
|
+
# Other commands, only return :do.
|
|
407
|
+
def type
|
|
408
|
+
command_chain.size.even? ? :undo : :redo
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
end # UndoRedoCommand
|
|
413
|
+
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
class EntryProcessor
|
|
4
|
+
|
|
5
|
+
# The queue whose entries are processed.
|
|
6
|
+
# Also the queue sending #entry_added.
|
|
7
|
+
attr_reader :queue
|
|
8
|
+
|
|
9
|
+
# Provides transactions
|
|
10
|
+
attr_accessor :transaction_controller
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
self.transaction_controller = NullTransactionController.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def queue=(aQueue)
|
|
17
|
+
queue.remove_watcher(self) if queue
|
|
18
|
+
@queue=aQueue
|
|
19
|
+
aQueue.add_watcher(self)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def _transact(err)
|
|
23
|
+
err ? transaction_controller.rollback : transaction_controller.commit
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Process the entry and commit its changes, if any.
|
|
27
|
+
def process(entry)
|
|
28
|
+
result = entry.do
|
|
29
|
+
commit_ok = true
|
|
30
|
+
err = result.error?
|
|
31
|
+
commit_ok = _transact(err) if entry.may_update
|
|
32
|
+
result.add_error('Commit failure') if !commit_ok
|
|
33
|
+
commit_ok && !err
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# ========================================
|
|
39
|
+
|
|
40
|
+
# Processes each command as it is received.
|
|
41
|
+
class NotifiedProcessor < EntryProcessor
|
|
42
|
+
|
|
43
|
+
def entry_added(entry)
|
|
44
|
+
queue.claim_entry(entry)
|
|
45
|
+
process(entry)
|
|
46
|
+
process(entry) while entry.retry?
|
|
47
|
+
queue.processed(entry)
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end # Processor
|
|
52
|
+
|
|
53
|
+
# ========================================
|
|
54
|
+
|
|
55
|
+
# A TransactionController that does nothing.
|
|
56
|
+
# For real transactions, see one of these (may need adaptors):
|
|
57
|
+
# * DBI http://ruby-dbi.sourceforge.net/
|
|
58
|
+
# * MySQL/Ruby http://www.tmtm.org/mysql/ruby/README.html
|
|
59
|
+
# * ODB http://brian.imxcc.com/odb/
|
|
60
|
+
# * Trans-simple http://raa.ruby-lang.org/project/trans-simple/
|
|
61
|
+
# * RDBC http://raa.ruby-lang.org/project/rdbc/
|
|
62
|
+
class NullTransactionController
|
|
63
|
+
|
|
64
|
+
def commit; true; end
|
|
65
|
+
def rollback; end
|
|
66
|
+
|
|
67
|
+
end # NullTransactionController
|
|
68
|
+
|
|
69
|
+
# ========================================
|
|
70
|
+
|
|
71
|
+
=begin rdoc
|
|
72
|
+
Mix this module into any class to give it the ability
|
|
73
|
+
to periodically kick of the do_behavior. Just send
|
|
74
|
+
it start and stop messages. These methods are asynchronous.
|
|
75
|
+
There are also synchronous versions that end in _synch.
|
|
76
|
+
Both versions take a Symbol that specifies the subtle
|
|
77
|
+
details of how the receiver should start or stop: see
|
|
78
|
+
VALID_START_SEMANTICS and VALID_STOP_SEMANTICS.
|
|
79
|
+
|
|
80
|
+
The do_behavior can be a Proc, Method, or Symbol.
|
|
81
|
+
It takes no arguments, should be thread safe, and
|
|
82
|
+
shuld be guaranteed not to raise an exception.
|
|
83
|
+
If your behavior might raise an exception, wrap
|
|
84
|
+
it in a Proc with exeption handling and logging.
|
|
85
|
+
|
|
86
|
+
This class offers some optional compensation for the time it
|
|
87
|
+
takes to execute do_behavior. Toward that end it
|
|
88
|
+
maintains a sequential list of the most recent
|
|
89
|
+
max_num_do_times measurements of the do_behavior.
|
|
90
|
+
|
|
91
|
+
This mixin is not currently thread safe: this feature
|
|
92
|
+
may be added later, but it does not look very necessary:
|
|
93
|
+
a single controller will probably manage all instances.
|
|
94
|
+
|
|
95
|
+
It was tempting to use a SimpleMachine to control the
|
|
96
|
+
internnal states. This does not buy us as much as it
|
|
97
|
+
would normally, perhaps because in this case most of
|
|
98
|
+
the events are internally generated.
|
|
99
|
+
def entry_state; :halted; end
|
|
100
|
+
def self.define_transitions
|
|
101
|
+
{
|
|
102
|
+
:halted => [:half_sleep, :sleep, :do],
|
|
103
|
+
:half_sleep => [:halted, :do],
|
|
104
|
+
:do => [:halted, :sleep],
|
|
105
|
+
:sleep => [:halted, :do]
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
def define_transitions; self.class.define_transitions; end
|
|
109
|
+
define_transit_tests(define_transitions)
|
|
110
|
+
write_missing_redispatch_templates(define_transitions)
|
|
111
|
+
=end
|
|
112
|
+
module Periodic
|
|
113
|
+
|
|
114
|
+
# Specifies the behavior that gets periodically
|
|
115
|
+
# executed. Either:
|
|
116
|
+
# * A Symbol executed by instance this is mixed into
|
|
117
|
+
# * A Proc
|
|
118
|
+
# * A Method
|
|
119
|
+
# Defaults to :process
|
|
120
|
+
attr_accessor :do_behavior
|
|
121
|
+
|
|
122
|
+
# A float representing either the sleep time,
|
|
123
|
+
# or the approximate time between invocations
|
|
124
|
+
# (depending on #subtract_do_time
|
|
125
|
+
attr_accessor :seconds
|
|
126
|
+
|
|
127
|
+
# A Boolean:
|
|
128
|
+
# * If true, attempt to adjust the sleep
|
|
129
|
+
# time so that #seconds includes the invocation time.
|
|
130
|
+
# * If false, #seconds represents the sleep time.
|
|
131
|
+
attr_accessor :subtract_do_time
|
|
132
|
+
|
|
133
|
+
# A Symbol that specifies the start semantics when
|
|
134
|
+
# #start is invoked without an argument,
|
|
135
|
+
attr_accessor :default_start_semantics
|
|
136
|
+
|
|
137
|
+
# A Symbol that specifies the stop semantics when
|
|
138
|
+
# #stop is invoked without an argument.
|
|
139
|
+
attr_accessor :default_stop_semantics
|
|
140
|
+
|
|
141
|
+
# An array of up to MAX_NUM_AVG Floats representing do times.
|
|
142
|
+
# All the times need to be kept, so that the do_times_total
|
|
143
|
+
# can be adjusted when a new measurement replaces an old one.
|
|
144
|
+
attr_accessor :do_times
|
|
145
|
+
|
|
146
|
+
# A float, the total of the values in do_times
|
|
147
|
+
attr_accessor :do_times_total
|
|
148
|
+
|
|
149
|
+
# An Integer that specifies the maximum number of
|
|
150
|
+
# measured execution times to keep track of when
|
|
151
|
+
# computing do_times_average
|
|
152
|
+
attr_reader :max_num_do_times
|
|
153
|
+
|
|
154
|
+
# Non nil while the instance is sleeping.
|
|
155
|
+
# We need to hold on to the thread so that
|
|
156
|
+
# it can be terminated if we need to stop
|
|
157
|
+
# immediately.
|
|
158
|
+
attr_reader :sleep_thread
|
|
159
|
+
|
|
160
|
+
# Non nil while the instance is performing
|
|
161
|
+
# the do_behavior.
|
|
162
|
+
# We need to hold on to the thread so that
|
|
163
|
+
# it can be terminated if we need to stop
|
|
164
|
+
# immediately.
|
|
165
|
+
attr_reader :do_thread
|
|
166
|
+
|
|
167
|
+
# A symbol that keeps track of the current state of the instance.
|
|
168
|
+
attr_reader :state
|
|
169
|
+
|
|
170
|
+
def initialize_periodic(seconds)
|
|
171
|
+
self.seconds=seconds
|
|
172
|
+
self.do_behavior=:process
|
|
173
|
+
self.subtract_do_time=true
|
|
174
|
+
self.default_start_semantics=:start_sleep
|
|
175
|
+
self.default_stop_semantics=:stop_during_sleep
|
|
176
|
+
self.do_times=Array.new
|
|
177
|
+
self.do_times_total=0.0
|
|
178
|
+
self.max_num_do_times=10
|
|
179
|
+
_halt!
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# This setter has the following side effects if the new value is smaller than the old one:
|
|
183
|
+
# * do_times is truncated
|
|
184
|
+
# * do_times_total is changed
|
|
185
|
+
def max_num_do_times=(int)
|
|
186
|
+
@max_num_do_times=int
|
|
187
|
+
return unless int<do_times.size
|
|
188
|
+
do_times = do_times[do_times.size-int, int]
|
|
189
|
+
do_times_total = do_times.inject(0.0) {|sum, val| sum+val }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# An Array of Symbols describing the first thing that happens
|
|
193
|
+
# when you send #start.
|
|
194
|
+
# * :start_do - The do_behavior is invoked, followed by a sleep.
|
|
195
|
+
# * :start_sleep - The receiver sleeps before executing the do_behavior for the first time.
|
|
196
|
+
# * :start_half_sleep - The receiver sleeps half the normal time before executing the do_behavior.
|
|
197
|
+
VALID_START_SEMANTICS = [:start_do, :start_sleep, :start_half_sleep]
|
|
198
|
+
|
|
199
|
+
# An Array of Symbols describing how to stop.
|
|
200
|
+
# * :stop_immediately - abort the do_behavior (if running) as well as the sleep.
|
|
201
|
+
# * :stop_during_sleep - Let the do_behavior finish, if it is running.
|
|
202
|
+
# If the receiver is sleeping, stop immedately.
|
|
203
|
+
# * :stop_after_next_do - Let the current sleep and the subsequent do_behavior finish
|
|
204
|
+
# before stopping. If the do_behavior is already running, let it finish, but don't
|
|
205
|
+
# sleep or run the do_behavior again after that.
|
|
206
|
+
VALID_STOP_SEMANTICS = [:stop_immediately, :stop_after_next_do, :stop_during_sleep]
|
|
207
|
+
|
|
208
|
+
# An Array of Symbols describing valid state
|
|
209
|
+
VALID_STATES = [:halted, :running, :halt_scheduled, :halt_after_do_scheduled]
|
|
210
|
+
|
|
211
|
+
# Returns a Float, the time in seconds that the instance
|
|
212
|
+
# should sleep between invocations.
|
|
213
|
+
def sleep_time
|
|
214
|
+
subtract_do_time ? seconds - do_times_average : seconds
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# A running average based on do_times_total
|
|
218
|
+
def do_times_average
|
|
219
|
+
do_times_total / do_times.size
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Start the reciever sychronousy according to start_semantics.
|
|
223
|
+
# Does not return until the instance has been stopped.
|
|
224
|
+
def start_synch(start_semantics=default_start_semantics)
|
|
225
|
+
fail "Invalid start_semantics: #{start_semantics.to_s}" unless VALID_START_SEMANTICS.include?(start_semantics)
|
|
226
|
+
_running!
|
|
227
|
+
case start_semantics
|
|
228
|
+
when :start_sleep
|
|
229
|
+
_sleep
|
|
230
|
+
when :start_half_sleep
|
|
231
|
+
_sleep(0.5)
|
|
232
|
+
end
|
|
233
|
+
while (_running? || _halt_after_do?)
|
|
234
|
+
_do
|
|
235
|
+
_halt! if halt_after_do?
|
|
236
|
+
_sleep if running
|
|
237
|
+
end
|
|
238
|
+
_halted!
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Start the reciever sychronousy according to stop_semantics.
|
|
242
|
+
# Does not return until the instance has been stopped.
|
|
243
|
+
def stop(stop_semantics=default_stop_semantics)
|
|
244
|
+
fail "Invalid stop_semantics: #{stop_semantics.to_s}" unless VALID_STOP_SEMANTICS.include?(stop_semantics)
|
|
245
|
+
case stop_semantics
|
|
246
|
+
when :stop_immediately
|
|
247
|
+
_halt!
|
|
248
|
+
_stop_thread(do_thread, stop_semantics)
|
|
249
|
+
_stop_thread(sleep_thread, stop_semantics)
|
|
250
|
+
when :stop_after_next_do
|
|
251
|
+
_halt_after_do!
|
|
252
|
+
# Don't stop any threads.
|
|
253
|
+
when :stop_during_sleep
|
|
254
|
+
_halt!
|
|
255
|
+
_stop_thread(sleep_thread, stop_semantics)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Start the receiver according to start_semantics, and return immediately.
|
|
260
|
+
def start(start_semantics=default_start_semantics)
|
|
261
|
+
Thread.new{ start_synch(start_semantics) }
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Schedule the receiver to stop, in the mannner specified by stop_semantics.
|
|
265
|
+
# Returns immediately. Depending on stop_semantics, the receiver may
|
|
266
|
+
# execute one more time.
|
|
267
|
+
def stop_synch(stop_semantics=default_stop_semantics)
|
|
268
|
+
stop_synch(stop_semantics)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def running?; :running == state; end
|
|
272
|
+
alias _running? running?
|
|
273
|
+
alias is_running? running?
|
|
274
|
+
|
|
275
|
+
private
|
|
276
|
+
|
|
277
|
+
def _add_do_time(t)
|
|
278
|
+
do_times << t
|
|
279
|
+
do_times_total += t
|
|
280
|
+
do_times_total -= do_times.shift if do_times.size>max_num_do_times
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def _do()
|
|
284
|
+
do_thread = Thread.current
|
|
285
|
+
startTime = Time.now
|
|
286
|
+
answer = case
|
|
287
|
+
when do_behavior.instance_of?(Symbol) : self.send(do_behavior)
|
|
288
|
+
when do_behavior.instance_of?(Proc) : do_behavior.call
|
|
289
|
+
when do_behavior.instance_of?(Method) : do_behavior.call
|
|
290
|
+
end
|
|
291
|
+
_add_do_time(Time.now-startTime)
|
|
292
|
+
do_thread = nil
|
|
293
|
+
rescue
|
|
294
|
+
ensure
|
|
295
|
+
answer
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def _sleep(fraction=1)
|
|
299
|
+
sleep_thead = Thread.current
|
|
300
|
+
sleep(sleep_time * fraction)
|
|
301
|
+
sleep_thread = nil
|
|
302
|
+
rescue
|
|
303
|
+
ensure
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def _stop_thread(thread, semantics)
|
|
307
|
+
thread.raise("Periodic mixin stopped with semantics #{semantics.to_s}") if thread
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Test state
|
|
311
|
+
def _halt_after_do?; :halt_after_do_scheduled == state; end
|
|
312
|
+
# Set state
|
|
313
|
+
def _running!; state = :running; end
|
|
314
|
+
def _halt!; state = :halt_scheduled; end
|
|
315
|
+
def _halted!; state = :halted; end
|
|
316
|
+
def _halt_after_do!; state = :halt_after_do_scheduled; end
|
|
317
|
+
|
|
318
|
+
end # Periodic
|
|
319
|
+
|
|
320
|
+
# ========================================
|
|
321
|
+
|
|
322
|
+
class PollingProcessor < EntryProcessor
|
|
323
|
+
include Periodic
|
|
324
|
+
|
|
325
|
+
# Prevents stale commands in the queue.
|
|
326
|
+
# The highest priority consideration in determining
|
|
327
|
+
# if the processor should process claims.
|
|
328
|
+
attr_accessor :max_command_age
|
|
329
|
+
|
|
330
|
+
# How much work the instance should request
|
|
331
|
+
# each time it processes commands.
|
|
332
|
+
# Insuficient work will result in a high transaction overhead.
|
|
333
|
+
attr_accessor :min_claim_time
|
|
334
|
+
|
|
335
|
+
# Large claim size increases odds of command conflict.
|
|
336
|
+
# An upper limit on how many commands will be
|
|
337
|
+
# processed at one time. Too many commands will increase
|
|
338
|
+
# the chance of a conflict. See also claim_size_limit
|
|
339
|
+
attr_accessor :max_claim_size
|
|
340
|
+
|
|
341
|
+
# Used to adjust the claim_size_limit. Normally 1.0.
|
|
342
|
+
# This is multiplied by the CLAIM_FRACTION_MULIPLIER
|
|
343
|
+
# each time a proccessing attempt fails. It is reset
|
|
344
|
+
# to 1.0 once a processing attempt succeeds.
|
|
345
|
+
attr_reader :claim_fraction
|
|
346
|
+
|
|
347
|
+
CLAIM_FRACTION_MULIPLIER=0.5
|
|
348
|
+
|
|
349
|
+
def initialize
|
|
350
|
+
initialize_periodic(1.0)
|
|
351
|
+
self.do_behavior=:action
|
|
352
|
+
self.max_max_periods_without_claims = 10
|
|
353
|
+
self.min_claim_size = 5
|
|
354
|
+
self.max_claim_size = 20
|
|
355
|
+
_reset
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def claim?
|
|
359
|
+
queue.age_oldest_available > max_command_age &&
|
|
360
|
+
queue.estimated_seconds > min_claim_time
|
|
361
|
+
end
|
|
362
|
+
alias should_claim claim?
|
|
363
|
+
|
|
364
|
+
def action
|
|
365
|
+
return unless claim?
|
|
366
|
+
entry = queue.claim_seconds(min_claim_time, claim_size_limit)
|
|
367
|
+
success = process(entry)
|
|
368
|
+
queue.processed(entry)
|
|
369
|
+
success ? _reset : _shrink
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Shrink the claim_size_limit by muliplying claim_fraction by CLAIM_FRACTION_MULTIPLIER
|
|
373
|
+
def _shrink
|
|
374
|
+
@claim_fraction *= CLAIM_FRACTION_MULTIPLIER
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
# Reset the claim_size_limit by resetting claim_fraction to 1.0
|
|
378
|
+
def _reset
|
|
379
|
+
@claim_fraction = 1.0
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
end # PollingProcessor
|