genie 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|