[Linux, OpenVMS, J2SE V6.0, JRuby] JRuby - Some notes

PRODUCT: JRuby Version 1.6.3 J2SE (TM) Development Kit (JDK) 6.0x for OpenVMS OpenJDK Runtime Environment (IcedTea6 1.8.2)
OP/SYS: Linux Fedora 15 OpenVMS IA64 V8.3-1H1
COMPONENT: Ruby language
SOURCE: Philippe Vouters Fontainebleau/France
LOW-COST HIGH-TECH: http://techno-star.fr
OVERVIEW: JRuby has been ported to OpenVMS Itanium servers. It brings almost all the richness of the Ruby language to your OpenVMS fingertips. JRuby is a Java implementation of the Ruby language, the same as Jython is for Python. Ruby codes are highlighted in the PROGRAMS section. Three pure OpenVMS Ruby codes are also demonstrated.
*** CAUTION *** These sample programs have been tested using JRuby V1.6.3 on Linux Fedora 15 and on OpenVMS IA64 V8.3-1H1. However, we cannot guarantee their effectiveness because of the possibility of error in transmitting or implementing them. They are meant to be used as templates for writing your own programs, and may require modification for use on your system.
BUILDING JRUBY ONTO OPENVMS ITANIUM SERVERS: For full details on how to build JRuby onto your OpenVMS Itanium server, refer to the following URL link in this knowledge database: ../tima/OpenVMS-JRuby-libffi-jffi-Rebuilding_JRuby-1.6.3_on_OpenVMS_servers.html A note to those running the Ruby's FFI samples below on both Linux and OpenVMS systems : if running Ruby codes including the Ruby statement "require 'ffi'", you then may exprience a runtime crash under JRuby 1.6.3 if you add to your /path/to/jruby (Linux) or $ jruby (OpenVMS) shell command the --1.9 option. To correct the situation, edit the file jruby-1.6.3/lib/ruby/site_ruby/shared/ffi/ffi.rb and comment out with the '#' character the line containing require "'ffi/enum'".
PROGRAMS NOTES: Because a Unix shell can accept more shell arguments than an OpenVMS shell (DCL), you are currently limited to seven Ruby code program arguments at the DCL prompt. To workaround this issue, activate the OpenVMS GNV's shell (bash) and run /path/to/jruby-1.6.3/bin/jrubyvms along with your Ruby code script and arguments. You may also dynamically pass Java and Jruby options to jrubyvms. This may be useful for you to best tune your application. For more information, refer to the command bash$ /path/to/jruby-1.6.3/bin/jrubyvms --help
PROGRAMS: Copyright (C) 2010 by Philippe.Vouters@laposte.net This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>;. ************ * test-array.rb ************ #!/usr/bin/env ruby # # This code works fine under both JRuby (Fedora 15 and OpenVMS) and # Ruby (Fedora 15) # # Linux Fedora 13 activation: # jruby.sh test-array.rb [arg1 [arg2]] # # OpenVMS activation: # jruby test-array.rb [arg1 [arg2]] # with: # $ sho symbol jruby # JRUBY == "@SYS$SYSDEVICE:[PROVMS.USO.jruby-1^.6^.3.bin]jruby.com" # if ARGV.length >=1 word = ARGV[0] else print "Enter a word: " $stdout.flush; word = $stdin.readline.chomp end if ARGV.length >=2 guess = ARGV[1] else print "Enter a character: " $stdout.flush; guess = $stdin.readline.chomp end wordarray=word.split(//) found="not " print guess," is " if wordarray.index(guess) != nil found="" end print found,"included in ",wordarray.join(" "),"\n" ************ * gettimeofday.rb ************ require 'rubygems' require 'ffi' class Timeval < FFI::Struct rb_maj, rb_min, rb_micro = RUBY_VERSION.split('.') if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/ layout :tv_sec => :ulong, :tv_usec => :ulong else layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 end end module LibC extend FFI::Library if FFI::Platform.openvms? libc = "DECC$SHR" else libc = "c" end ffi_lib libc if FFI::Platform.openvms? attach_function :gettimeofday, :"decc$gettimeofday", [:pointer, :pointer], :int else attach_function :gettimeofday, [:pointer, :pointer], :int end end t = Timeval.new LibC.gettimeofday(t.pointer, nil) puts "t.tv_sec=#{t[:tv_sec]} t.tv_usec=#{t[:tv_usec]}" ************ * TimerDiffusion.rb ************ #!/usr/bin/env ruby # # This code without the trap block only works under a real Ruby written in C. # It does not work under any JRuby 1.5.3 (Linux Fedora 13 or OpenVMS V8.3-1H1). # The reason is that JRuby does not trap CTRL-C with a specific Java code. # So a CTRL-C typed on this code aborts the Java Virtual Machine. # # Different samples of this code in different languages including Java with # CTRL-C interception can be found at: # ../tima/All-OS-Java-Python-Ruby-translating-C-threaded-program-study.html # # This problem of JRuby 1.5.3 not handling CTRL-C has been reported into JRuby # bugtracker. From : # https://jira.codehaus.org/browse/JRUBY-5587?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel # the resolution of this problem report is Won't fix. However the workaround is # to use the "trap 'INT' do Thread.main.raise Interrupt end" block and to handle # the CRTL-C interrupt in a rescue Interrupt block. For more information, refer # to http://jira.codehaus.org/browse/JRUBY-4637 # Without the trap block below, a CTRL-C keyboard interrupt aborts the JVM # running JRuby. # The trap block must be placed BEFORE the begin .. rescue .. block # otherwise it is not taken into account by JRuby (Ruby ????). # # OpenVMS output: # # $ sho sys/noproc # OpenVMS V8.3-1H1 on node THESEE 17-JUL-2011 22:00:13.20 Uptime 382 03:0:45 # $ jruby TimerDiffusion.rb 2 10 # Cancel # # <CTRL-C> hit ! Can't wait until program finished ? # Got killed. Thread exiting ... # Got killed. Thread exiting ... require 'thread' thread = [] class <<thread attr :timeout def start_thread(minPrime) # Constructor self[self.length]=Thread.new { @timeout = minPrime.to_f # convert string to float run } end def run begin sleep(@timeout) rescue Interrupt => boom puts boom end end end # Main body # # The trap block hereafter is compulsary under JRuby and causes no difference # with or without under both tested C based Ruby 1.8.7 and Ruby 1.9.2 versions. # This is one runtime difference between a Java based Ruby and a C based Ruby. # trap 'INT' do Thread.main.raise Interrupt end i=ARGV.first.to_i(base=10) i.times {thread.start_thread(ARGV.last)} Thread.pass begin thread.each{ |oneThread| oneThread.join } puts "You're really patient ! Program finished" rescue Interrupt puts "<CTRL-C> hit ! Can't wait until program finished ? " thread.each {|thisThread| if thisThread.status != nil thisThread.raise(Interrupt,"Got killed. Thread exiting ... ") # # Calling the Thread join method is compulsary # under ruby 1.9.2p180 (2011-02-18 revision 30909) # and makes no difference with or without under # ruby 1.8.7 (2011-02-18 patchlevel 334). # Would this mean that ruby 1.8.7 makes an implicit thread # join on main thread exit letting the dynamic threads to # complete whereas ruby 1.9.2 does not ? # thisThread.join end } end ************ * Create_Delete_subdirectory.rb ************ #!/usr/bin/env ruby # # This code is the Ruby version of the pure Java code # available at: # ../tima/OpenVMS-Java-Directories_deletion_w_o_the_BYPASS_granted_privilege.html # # Under OpenVMS, and because the C based Ruby code has not been ported, it is # tested under JRuby/VMS. As JRuby is Java based, this code when executed under # JRuby/VMS requires the JAVA$CREATE_DIR_WITH_OWNER_DELETE logical to be set # prior to any JRuby execution of this code. This Java/VMS logical and its # setting is only compulsary provided your VMS process is NOT granted the # BYPASS privilege. This requirement with JRuby/VMS is made or will shortly be # made totally transparent to the JRuby/VMS user. # # Code inspired from Ruby statements or summary found at: # http://www.tutorialspoint.com/ruby/ruby_input_output.htm # and # http://www.zenspider.com/Languages/Ruby/QuickRef.html # if ARGV.length != 1 puts "Usage : " + __FILE__ + " expecting a subdirectory name as an argument" exit 1 end if File::exists?(ARGV[0]) and not File::directory?(ARGV[0]) puts "Usage : " + __FILE__ + " file exists and is not a directory" exit 1 end if File::exists?(ARGV[0]) and File::directory?(ARGV[0]) file_array = Dir.glob(ARGV[0]) if file_array != nil puts "Usage : " + __FILE__ + " directory exists and is not empty" exit 1 end end if not File::exists?(ARGV[0]) Dir.mkdir(ARGV[0]) end Dir.delete(ARGV[0]) if File::exists?(ARGV[0]) puts __FILE__ + " do not succeed to delete " + ARGV[0] + " directory. Check directory protections" exit 1 else puts __FILE__ + " successfully deleted " + ARGV[0] + " directory" end
THREE RUBY PURE OPENVMS EXAMPLES: ************ * DECC_test.rb ************ # # This code is portable using JRuby on both # Linux Fedora 13 and OpenVMS V8.3-1H1 # # Program's display: # $ jruby DECC_test.rb foo bar # Hello, World! # Argument 0: foo # Argument 1: bar # require 'ffi' require 'ffi/platform' module Portablelibc extend FFI::Library if FFI::Platform.openvms? libc = "DECC$SHR" else libc = "c" end ffi_lib libc if FFI::Platform.openvms? attach_function :printf, :"decc$txprintf", [:string, :varargs], :int else attach_function :printf, [:string, :varargs], :int end end Portablelibc.printf("Hello, World!\n") if ARGV.length > 1 ARGV.length.times do |i| Portablelibc.printf("Argument %d: %s\n", :int, i, :string, ARGV[i]) end end ************ * MyRTLTest.rb ************ # Program's display: # $ jruby MyRTLTest.rb # BlahBlah # lib$put_output status = 1 require 'ffi' module Librtl extend FFI::Library ffi_lib "LIBRTL" attach_function :lib_put_output, :"lib$put_output", [ :pointer], :int DSC_K_DTYPE_T = 14 DSC_K_CLASS_S = 1 class Descriptor_S < FFI::Struct layout :dsc_w_length, :short, 0, :dsc_b_dtype, :char, 2, :dsc_b_class, :char, 3, :dsc_a_pointer, :pointer, 4 # Alternative : # :dsc_a_pointer, :string, 4 end end def set_descriptor_S(s) obj = Librtl::Descriptor_S.new obj[:dsc_w_length] = s.length obj[:dsc_b_dtype] = Librtl::DSC_K_DTYPE_T obj[:dsc_b_class] = Librtl::DSC_K_CLASS_S obj[:dsc_a_pointer] = FFI::MemoryPointer.from_string(s) # Alternative : # obj[:dsc_a_pointer] = s return obj end puts "lib$put_output status = " + Librtl.lib_put_output( set_descriptor_S("BlahBlah") ).to_s ************ * VMS_SYSCalls.rb ************ # Program's display: # jruby VMS_SYSCalls.rb # VMS system time is : 12-NOV-2010 04:31:01.67 # require 'ffi' module VMS_SYSCalls extend FFI::Library ffi_lib "/SYS$COMMON/SYSLIB/SYS$PUBLIC_VECTORS.EXE" attach_function :sys_gettim, :"SYS$GETTIM", [:pointer], :int attach_function :sys_asctim, :"SYS$ASCTIM", [:pointer, :pointer, :pointer, :char], :int DSC_K_DTYPE_T = 14 DSC_K_CLASS_S = 1 class Descriptor_S < FFI::Struct layout :dsc_w_length, :short, 0, :dsc_b_dtype, :char, 2, :dsc_b_class, :char, 3, :dsc_a_pointer, :pointer, 4 end end timadr = FFI::MemoryPointer::new(:long, 1) status = VMS_SYSCalls.sys_gettim(timadr) if (status % 2) == 0 puts "sys$gettim returned error : "+status.to_s exit(status) end timlen = FFI::MemoryPointer::new(:short, 1) mallocSize = 23 timbuf = FFI::MemoryPointer::new(:char, mallocSize) mydescr = VMS_SYSCalls::Descriptor_S.new mydescr[:dsc_w_length] = mallocSize mydescr[:dsc_b_dtype] = VMS_SYSCalls::DSC_K_DTYPE_T mydescr[:dsc_b_class] = VMS_SYSCalls::DSC_K_CLASS_S mydescr[:dsc_a_pointer] = timbuf status = VMS_SYSCalls.sys_asctim(timlen,mydescr,timadr,0) if (status % 2) == 0 puts "sys$asctim returned error : "+status.to_s exit(status) end puts "VMS system time is : "+ timbuf.get_string(0,timlen.get_short(0))
TWO OTHER LIBFFI BASED PORTS: ../tima/OpenVMS-Python-ctypes-libffi-Python_module_ctypes.html ../tima/OpenVMS-IA64-Java-JNA-libffi-Porting_JNA_to_OpenVMS_Itanium_servers.html
TRIBUTES: Thanks go to X9000 company for letting me access to its OpenVMS Itanium computer. Special thanks go to Mister Thierry Uso for his active participation in this JRuby port onto OpenVMS Itanium servers. Thanks go as well to the Opensource world for wide opening their work at source level and for the unprecedented quality of their software, quality rarely found in closed source proprietary software.
REFERENCE(S): A JRuby blog at: http://www.nearinfinity.com/blogs/jruby/ JRuby Press release http://www.infoq.com/articles/state-of-jruby JRuby FFI explanations and examples at: https://github.com/ffi/ffi/wiki/Examples FFI receipes http://zegoggl.es/2009/05/ruby-ffi-recipes.html JRuby useful link: http://kenai.com/projects/jruby/pages/Home
Did you find this helpful?