lib/openwfe/expool/wfidgen.rb in ruote-0.9.18 vs lib/openwfe/expool/wfidgen.rb in ruote-0.9.19

- old
+ new

@@ -1,34 +1,34 @@ # #-- # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org # All rights reserved. -# -# Redistribution and use in source and binary forms, with or without +# +# Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # . Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# . Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation +# list of conditions and the following disclaimer. +# +# . Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# +# # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #++ # # @@ -44,345 +44,347 @@ require 'openwfe/service' require 'openwfe/rudefinitions' module OpenWFE - - # - # This default wfid generator outputs a long integer as a String. - # The last given id (in order to prevent clocks being put back) is - # stored in the work directory in the file "wfidgen.last" - # - class DefaultWfidGenerator < Service - def initialize (service_name, application_context) + # + # This default wfid generator outputs a long integer as a String. + # The last given id (in order to prevent clocks being put back) is + # stored in the work directory in the file "wfidgen.last" + # + class DefaultWfidGenerator < Service - super + def initialize (service_name, application_context) - @last = -1 - @mutex = Mutex.new + super - @last_fn = get_work_directory + '/wfidgen.last' + @last = -1 + @mutex = Mutex.new - load_last() + @last_fn = get_work_directory + '/wfidgen.last' - ensure_last_f - end + load_last() - # - # Returns a new workflow instance id - # - # The launchitem parameter is not used by this generator. - # - def generate (launchitem=nil) + ensure_last_f + end - wfid = nil + # + # Returns a new workflow instance id + # + # The launchitem parameter is not used by this generator. + # + def generate (launchitem=nil) - @mutex.synchronize do - wfid = now - wfid = @last + 1 if wfid <= @last - @last = wfid - save_last - end + wfid = nil - to_string(wfid) - end + @mutex.synchronize do + wfid = now + wfid = @last + 1 if wfid <= @last + @last = wfid + save_last + end - # - # The actual job of turning the numeric result into a String. - # This method is overriden in extension of this class. - # - def to_string (numeric_id) + to_string(wfid) + end - numeric_id.to_s - end + # + # The actual job of turning the numeric result into a String. + # This method is overriden in extension of this class. + # + def to_string (numeric_id) - # - # Is a simple call to OpenWFE::split_wfid() - # - def split_wfid (wfid) + numeric_id.to_s + end - OpenWFE.split_wfid(wfid) - end + # + # Is a simple call to OpenWFE::split_wfid() + # + def split_wfid (wfid) - # - # This method is called by OpenWFE::split_wfid() when it has detected - # a wfid following this 'defaut' scheme. - # - def self.split_wfid (wfid) + OpenWFE.split_wfid(wfid) + end - r = [] - 0.upto(wfid.length-1) do |i| - r << wfid[i, 1] - end + # + # This method is called by OpenWFE::split_wfid() when it has detected + # a wfid following this 'defaut' scheme. + # + def self.split_wfid (wfid) - r - end + r = [] + 0.upto(wfid.length-1) do |i| + r << wfid[i, 1] + end - # - # Stops this service. - # In this particular implementation, makes sure the "wfidgen.last" - # file is closed. - # - def stop + r + end - #linfo { "stop() stopping '#{@service_name}'" } - @last_f.close if @last_f - end + # + # Stops this service. + # In this particular implementation, makes sure the "wfidgen.last" + # file is closed. + # + def stop - protected + #linfo { "stop() stopping '#{@service_name}'" } + if @last_f + @last_f.close rescue nil + end + end - def ensure_last_f - if (not @last_f) or @last_f.closed? - begin - @last_f = File.open(@last_fn, "w+") - rescue Exception => e - lwarn do - "new() failed to open #{@last_fn}, "+ - "continuing anyway...\n"+ - OpenWFE::exception_to_s(e) - end - end - end - end + protected - def now - wfid = Time.now.to_f * 1000 * 10 - wfid.to_i + def ensure_last_f + if (not @last_f) or @last_f.closed? + begin + @last_f = File.open(@last_fn, "w+") + rescue Exception => e + lwarn do + "new() failed to open #{@last_fn}, "+ + "continuing anyway...\n"+ + OpenWFE::exception_to_s(e) end + end + end + end - def save_last - return unless @last_f - ensure_last_f() - @last_f.pos = 0 - @last_f.puts @last - end + def now + wfid = Time.now.to_f * 1000 * 10 + wfid.to_i + end - def load_last - @mutex.synchronize do + def save_last + return unless @last_f + ensure_last_f() + @last_f.pos = 0 + @last_f.puts @last + end - if File.exist?(@last_fn) - begin - s = File.open(@last_fn, "r") do |f| - f.readline - end - @last = Integer(s) - #puts @last - rescue Exception => e - #puts - #puts e.to_s - end - end + def load_last + @mutex.synchronize do - n = now - - @last = n if (not @last) or (@last < n) - end + if File.exist?(@last_fn) + begin + s = File.open(@last_fn, "r") do |f| + f.readline + end + @last = Integer(s) + #puts @last + rescue Exception => e + #puts + #puts e.to_s end - end + end - # - # This extension of DefaultWfidGenerator produces ids like - # "20070318-jonowoguya" or "20071224-jesoshimoha" that are a bit - # easier to grasp than full integer wfids. - # - # Now relying on the 'rufus-mnemo' gem. - # - class KotobaWfidGenerator < DefaultWfidGenerator + n = now - # - # Overrides the to_string() method of the DefaultWfidGenerator, - # - def to_string (numeric_id) - - self.class.to_string(numeric_id) + @last = n if (not @last) or (@last < n) end + end + end - # - # That's here that the numeric wfid gets turned into a 'kotoba'. - # A static method easily accessible by any. - # - def self.to_string (numeric_id) + # + # This extension of DefaultWfidGenerator produces ids like + # "20070318-jonowoguya" or "20071224-jesoshimoha" that are a bit + # easier to grasp than full integer wfids. + # + # Now relying on the 'rufus-mnemo' gem. + # + class KotobaWfidGenerator < DefaultWfidGenerator - i = numeric_id % (10 * 1000 * 60 * 60 * 24) - t = Time.now.gmtime + # + # Overrides the to_string() method of the DefaultWfidGenerator, + # + def to_string (numeric_id) - s = sprintf "%4d%02d%02d", t.year, t.month, t.day - s << "-" - s << Rufus::Mnemo::from_integer(i) - s - end + self.class.to_string(numeric_id) + end - # - # This method is called by OpenWFE::split_wfid() when it has detected - # a wfid following the 'kotoba' scheme. - # Returns the 'kotoba' wfid split into its syllables - # - def self.split_wfid (wfid) + # + # That's here that the numeric wfid gets turned into a 'kotoba'. + # A static method easily accessible by any. + # + def self.to_string (numeric_id) - Rufus::Mnemo::split(wfid[9..-1]) - end + i = numeric_id % (10 * 1000 * 60 * 60 * 24) + t = Time.now.gmtime - # - # Turns a KotobaWfidGenerator produced wfid into a UTC date. - # - def self.to_time (wfid) + s = sprintf "%4d%02d%02d", t.year, t.month, t.day + s << "-" + s << Rufus::Mnemo::from_integer(i) + s + end - year = wfid[0, 4] - month = wfid[4, 2] - day = wfid[6, 2] + # + # This method is called by OpenWFE::split_wfid() when it has detected + # a wfid following the 'kotoba' scheme. + # Returns the 'kotoba' wfid split into its syllables + # + def self.split_wfid (wfid) - s = wfid[9..-1] - - i = Rufus::Mnemo::to_integer(s) - - hour = (i / (10000 * 60 * 60)) % 24 - min = (i / (10000 * 60)) % 60 - sec = (i / 10000) % 60 - usec = (i * 100) % 1000000 - - #puts "hms #{hour} #{min} #{sec} #{usec}" - - Time.utc(year, month, day, hour, min, sec, usec) - end - - def self.from_time (t) - - to_string(t.to_f * 10 * 1000).to_i - end + Rufus::Mnemo::split(wfid[9..-1]) end # - # This wfid generator returns as wfid the value found in a given - # field of the launchitem (if any). + # Turns a KotobaWfidGenerator produced wfid into a UTC date. # - # If there is no launchitem or no field, a Kotoba wfid is returned. - # - # This generator is useful for engines that have to use workflow - # instance ids generated by other systems. - # - class FieldWfidGenerator < KotobaWfidGenerator + def self.to_time (wfid) - def initialize (service_name, application_context, field_name) + year = wfid[0, 4] + month = wfid[4, 2] + day = wfid[6, 2] - super service_name, application_context + s = wfid[9..-1] - @field_name = field_name - end + i = Rufus::Mnemo::to_integer(s) - def generate (launchitem=nil) + hour = (i / (10000 * 60 * 60)) % 24 + min = (i / (10000 * 60)) % 60 + sec = (i / 10000) % 60 + usec = (i * 100) % 1000000 - return super unless launchitem + #puts "hms #{hour} #{min} #{sec} #{usec}" - wfid = launchitem.attributes[@field_name] + Time.utc(year, month, day, hour, min, sec, usec) + end - return wfid.to_s if wfid + def self.from_time (t) - super - # - # if the field is not present in the launchitem, will - # return a Kotoba wfid - end + to_string(t.to_f * 10 * 1000).to_i end + end - # - # A wfid generator that uses any underlying "uuidgen" command it might - # find. - # By default, it favours "uuidgen -t". - # - # You can specifying a command by passing a :uuid_command param in the - # application context, or simply by overriding the generate() method. - # - class UuidWfidGenerator < Service + # + # This wfid generator returns as wfid the value found in a given + # field of the launchitem (if any). + # + # If there is no launchitem or no field, a Kotoba wfid is returned. + # + # This generator is useful for engines that have to use workflow + # instance ids generated by other systems. + # + class FieldWfidGenerator < KotobaWfidGenerator - COMMANDS = [ - "uuidgen -t", - "uuidgen" - ] + def initialize (service_name, application_context, field_name) - def initialize (service_name, application_context) + super service_name, application_context - super + @field_name = field_name + end - @command = @application_context[:uuid_command] \ - if @application_context + def generate (launchitem=nil) - unless @command - COMMANDS.each do |c| - c = "#{c} 2> /dev/null" - s = `#{c}` - h = s[0, 8].hex - if h > 0 - @command = c - break - end - end - end + return super unless launchitem - raise "no command found for generating an uuid found..." \ - unless @command + wfid = launchitem.attributes[@field_name] - linfo { "new() command that will be used : '#{@command}'" } - end + return wfid.to_s if wfid + super # - # Generates a brand new UUID - # - # The launchitem parameter is not used by this generator. - # - def generate (launchitem=nil) + # if the field is not present in the launchitem, will + # return a Kotoba wfid + end + end - `#{@command}`.chomp - end + # + # A wfid generator that uses any underlying "uuidgen" command it might + # find. + # By default, it favours "uuidgen -t". + # + # You can specifying a command by passing a :uuid_command param in the + # application context, or simply by overriding the generate() method. + # + class UuidWfidGenerator < Service - # - # Is a simple call to OpenWFE::split_wfid() - # - def split_wfid (wfid) + COMMANDS = [ + "uuidgen -t", + "uuidgen" + ] - OpenWFE.split_wfid(wfid) - end + def initialize (service_name, application_context) - # - # This method is called by OpenWFE::split_wfid() when it has detected - # a wfid that is a UUID. - # - # Splits the first part of the uuid (will be used for the - # expression storage directory structure). - # - def self.split_wfid (wfid) + super - s = wfid[0, 8] - a = [] - 4.times do |i| - a << s[i*2, 2] - end - a + @command = @application_context[:uuid_command] \ + if @application_context + + unless @command + COMMANDS.each do |c| + c = "#{c} 2> /dev/null" + s = `#{c}` + h = s[0, 8].hex + if h > 0 + @command = c + break + end end + end + + raise "no command found for generating an uuid found..." \ + unless @command + + linfo { "new() command that will be used : '#{@command}'" } end # - # "module methods" + # Generates a brand new UUID # + # The launchitem parameter is not used by this generator. + # + def generate (launchitem=nil) - SPLIT_MAP = { - "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" => UuidWfidGenerator, - "[0-9]{8}-[a-z]*" => KotobaWfidGenerator - } + `#{@command}`.chomp + end # - # This method should be able to split any wfid whose scheme is implemented - # here. + # Is a simple call to OpenWFE::split_wfid() # - def OpenWFE.split_wfid (wfid) + def split_wfid (wfid) - SPLIT_MAP.each do |regex, clazz| - return clazz.split_wfid(wfid) if wfid.match(regex) - end - # - # else - # - DefaultWfidGenerator.split_wfid(wfid) + OpenWFE.split_wfid(wfid) end + + # + # This method is called by OpenWFE::split_wfid() when it has detected + # a wfid that is a UUID. + # + # Splits the first part of the uuid (will be used for the + # expression storage directory structure). + # + def self.split_wfid (wfid) + + s = wfid[0, 8] + a = [] + 4.times do |i| + a << s[i*2, 2] + end + a + end + end + + # + # "module methods" + # + + SPLIT_MAP = { + "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" => UuidWfidGenerator, + "[0-9]{8}-[a-z]*" => KotobaWfidGenerator + } + + # + # This method should be able to split any wfid whose scheme is implemented + # here. + # + def OpenWFE.split_wfid (wfid) + + SPLIT_MAP.each do |regex, clazz| + return clazz.split_wfid(wfid) if wfid.match(regex) + end + # + # else + # + DefaultWfidGenerator.split_wfid(wfid) + end end