Class: SpoolPool::Pool
- Inherits:
-
Object
- Object
- SpoolPool::Pool
- Defined in:
- lib/spool_pool/pool.rb
Overview
This is a container class used to manage the interaction with the individual Spool instances. Spool directories are created using the name given in the put/get methods on demand as subdirectories of the spool_dir passed to the initializer..
Security Note
Some naive tests are in place to catch the most blatant directory traversal attempts. But for real security you should never blindly pass any user-supplied or computed queue name to these methods. Always validate user input!
Instance Attribute Summary collapse
-
#spool_dir ⇒ Object
readonly
Returns the value of attribute spool_dir.
-
#spools ⇒ Object
readonly
Returns the value of attribute spools.
Class Method Summary collapse
-
.validate_pool_dir(directory) ⇒ Object
Sanity checking of the given pool
directoryand it’s children (and parent, if thedirectoryitself doesn’t exist yet).
Instance Method Summary collapse
-
#flush(spool, &block) ⇒ Object
Retrieves and deserializes all data in the given
spool, yielding each deserialized data to the supplied block. -
#get(spool, &block) ⇒ Object
Retrieves and deserializes oldest data in the given
spool, yielding it to an optional block as well. -
#initialize(spool_path) ⇒ Pool
constructor
Sets up a spooling pool in the
spool_pathgiven. -
#put(spool, data) ⇒ Object
Serializes and stores the
datain the givenspool.
Constructor Details
#initialize(spool_path) ⇒ Pool
Sets up a spooling pool in the spool_path given. If the directory does not exist, it will try to create it for you.
Will throw an exception if it can’t create the directoy, or if the directory exists and is not read- and writeable by the effective user id of the process.
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/spool_pool/pool.rb', line 66 def initialize( spool_path ) @spool_dir = Pathname.new spool_path @spools = {} self.class.validate_pool_dir( spool_path ) setup_spooldir unless @spool_dir.exist? assert_readable @spool_dir assert_writeable @spool_dir end |
Instance Attribute Details
#spool_dir ⇒ Object (readonly)
Returns the value of attribute spool_dir.
19 20 21 |
# File 'lib/spool_pool/pool.rb', line 19 def spool_dir @spool_dir end |
#spools ⇒ Object (readonly)
Returns the value of attribute spools.
20 21 22 |
# File 'lib/spool_pool/pool.rb', line 20 def spools @spools end |
Class Method Details
.validate_pool_dir(directory) ⇒ Object
Sanity checking of the given pool directory and it’s children (and parent,
if the +directory+ itself doesn't exist yet).
Will throw an exception if anything permission-wise looks fishy.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/spool_pool/pool.rb', line 28 def self.validate_pool_dir( directory ) pool_dir = Pathname.new( directory ) begin if !pool_dir.exist? raise Errno::EACCES unless pool_dir.parent.writable? and pool_dir.parent.executable? return end raise Errno::EACCES unless pool_dir.readable? and pool_dir.writable? and pool_dir.executable? return if pool_dir.children.empty? pool_dir.children.select{ |d| d.dir? }.each do |spool_dir| raise Errno::EACCES unless spool_dir.readable? and spool_dir.writable? and spool_dir.executable? spool_dir.children.select{ |f| f.file? }.each do |spool_file| raise Errno::EACCES unless spool_file.readable? end end rescue Errno::EACCES raise Errno::EACCES.new( "Something doesn't look right permission wise. Consider running 'chmod -R 0755 #{directory}' or the equivalent. If the #{directory} itself doesn't exist, check to make sure it's parent exists, and is write- and executable for the current process owner." ) end end |
Instance Method Details
#flush(spool, &block) ⇒ Object
Retrieves and deserializes all data in the given spool, yielding each deserialized data to the supplied block. Ordering is oldest data first.
Note that while data is retrieved oldest first, the order is non-strict, i.e. different data written during the same second to the storage will be retrieved in a random order. Or to put it another way: Ordering is exact down to the second, but sub-second ordering is random.
This method performs a naive check on the spool name for directory traversal attempts. *DO NOT* rely on this for security relevant systems, always validate user supplied queue names yourself before handing them off to this method!
135 136 137 138 139 140 141 |
# File 'lib/spool_pool/pool.rb', line 135 def flush( spool, &block ) validate_spool_path spool missing_spool_on_read_handler( spool ) unless @spools.has_key?( spool ) @spools[spool].flush( &block ) if @spools[spool] end |
#get(spool, &block) ⇒ Object
Retrieves and deserializes oldest data in the given spool, yielding it to an optional block as well. The spool file is deleted just before the method returns. If a block was given, and an exception was raised within the block, the spool file is not deleted and another try at processing can be attempted in the future.
Note that while data is retrieved oldest first, the order is non-strict, i.e. different data written during the same second to the storage will be retrieved in a random order. Or to put it another way: Ordering is exact down to the second, but sub-second ordering is random.
This method performs a naive check on the spool name for directory traversal attempts. *DO NOT* rely on this for security relevant systems, always validate user supplied queue names yourself before handing them off to this method!
111 112 113 114 115 116 117 118 119 |
# File 'lib/spool_pool/pool.rb', line 111 def get( spool, &block ) validate_spool_path spool missing_spool_on_read_handler( spool ) unless @spools.has_key?( spool ) data = nil data = @spools[spool].get( &block ) if @spools[spool] data end |
#put(spool, data) ⇒ Object
Serializes and stores the data in the given spool. If the spool doesn’t exist yet, it will try to create a new spool and directory.
Returns the path of the file storing the data.
This method performs a naive check on the spool name for directory traversal attempts. *DO NOT* rely on this for security relevant systems, always validate user supplied queue names yourself before handing them off to this method!
88 89 90 91 92 |
# File 'lib/spool_pool/pool.rb', line 88 def put( spool, data ) validate_spool_path spool @spools[spool] ||= SpoolPool::Spool.new( @spool_dir + spool.to_s ) @spools[spool].put( data ) end |