[#29932] Happy 2002! — "Rich Kilmer" <rich@...>

Happy New Year from Washington DC!

24 messages 2002/01/01
[#29938] RE: Happy 2002! — "James Britt (rubydev)" <james@...> 2002/01/01

>

[#29954] Re: Happy 2002! — Dinakar <Desai.Dinakar@...> 2002/01/01

"James Britt (rubydev)" wrote:

[#29991] Execing command with backquotes — mail02@... (Frank Benoit)

Hi

13 messages 2002/01/01

[#30101] Ruby Weekly News rdf feed now available — Dave Thomas <Dave@...>

12 messages 2002/01/03

[#30191] chomp for arrays? — dempsejn@...

Hi All,

25 messages 2002/01/04
[#30238] Re: chomp for arrays? — adamspitz@... (Adam Spitz) 2002/01/04

How about something like this?

[#30248] Re: chomp for arrays? — Massimiliano Mirra <list@...> 2002/01/05

On Sat, Jan 05, 2002 at 04:53:14AM +0900, Adam Spitz wrote:

[#30357] snippet exchange (was: Re: Re: chomp for arrays?) — David Alan Black <dblack@...> 2002/01/06

Hello --

[#30369] Re: snippet exchange (was: Re: Re: chomp for arrays?) — "Mark Hahn" <mchahn@...> 2002/01/06

A daydream of mine is a "super-require" that if the file was not found, the

[#30401] Re: snippet exchange (was: Re: Re: chomp for arrays?) — Dan Sugalski <dan@...> 2002/01/07

At 06:31 AM 1/7/2002 +0900, Mark Hahn wrote:

[#30195] should I use ruby instead of perl — vekkuli ketkutin <qvyht@...>

simple question...

25 messages 2002/01/04

[#30265] Structs and Marshalling — Albert Wagner <alwagner@...>

I keep getting myself tripped up when I Marshal Struct objects. I typically

18 messages 2002/01/05
[#30281] Re: Structs and Marshalling — ts <decoux@...> 2002/01/05

>>>>> "A" == Albert Wagner <alwagner@tcac.net> writes:

[#30334] Re: Structs and Marshalling — Albert Wagner <alwagner@...> 2002/01/06

On Saturday 05 January 2002 06:25 am, you wrote:

[#30473] Re: [ruby-talk:30334] Re: Structs and Marshalling — matz@... (Yukihiro Matsumoto) 2002/01/07

Hi,

[#30528] Possible bug with struct.c (Re: Re: Structs and Marshalling) — ts <decoux@...> 2002/01/07

>>>>> "Y" == Yukihiro Matsumoto <matz@ruby-lang.org> writes:

[#30546] Re: Possible bug with struct.c (Re: Re: Structs and Marshalling) — nobu.nokada@... 2002/01/07

At Tue, 8 Jan 2002 02:36:12 +0900,

[#30274] The Ruby Way — "Conrad Schneiker" <schneiker@...>

Hi,

31 messages 2002/01/05
[#30275] RE: The Ruby Way — "Curt Hibbs" <curt@...> 2002/01/05

> From: Conrad Schneiker [mailto:schneiker@jump.net]

[#30276] Re: The Ruby Way — "Curt Hibbs" <curt@...> 2002/01/05

That was supposed to say "how do I implement a hash with duplicate keys?"

[#30320] Sorting a Hash by value of integer stored in the Hash — Michael Joner <finalfrontier@...>

I have a program which creates a Hash array. The ultimate result is a

14 messages 2002/01/06

[#30327] one liner / overriden class repository — "Jack Dempsey" <dabigdemp@...>

Why aim if not high? :-)

15 messages 2002/01/06

[#30366] class name reported differently in different contexts — Joel VanderWerf <vjoel@...>

30 messages 2002/01/06
[#30380] Re: class name reported differently in different contexts — "Chr. Rippel" <chr_news@...> 2002/01/06

[#30496] Re: class name reported differently in different contexts — <ale@...> 2002/01/07

On Mon, 7 Jan 2002, Chr. Rippel wrote:

[#30372] [ANN] Invitation to join LotY (Language of the Year) project, 2002: learning Haskell — David Alan Black <dblack@...>

Dear fellow programmers,

10 messages 2002/01/06

[#30431] Re: snippet exchange (was: Re: Re: chomp for arrays?) — "Jack Dempsey" <dabigdemp@...>

The way i was thinking of this working would be this: someone has heard of a

14 messages 2002/01/07

[#30461] Re: the [ruby-talk] is gone? — "Jack Dempsey" <dabigdemp@...>

Hi Matz,

13 messages 2002/01/07

[#30494] Segfault with druby and fork — Michael Witrant <mike@...>

Hello,

24 messages 2002/01/07
[#30510] Re: Segfault with druby and fork — matz@... (Yukihiro Matsumoto) 2002/01/07

Hi,

[#30543] Re: Segfault with druby and fork — Michael Witrant <mike@...> 2002/01/07

On Tue, 8 Jan 2002 00:37:14 +0900

[#30640] Re: Segfault with druby and fork — matz@... (Yukihiro Matsumoto) 2002/01/08

Hi,

[#30644] An Update on the FreeRIDE Project — "Curt Hibbs" <curt@...> 2002/01/08

I wanted to give everyone an update on where we are with the FreeRIDE

[#30655] Re: An Update on the FreeRIDE Project — bobx@... (Bob) 2002/01/08

Documentation should also be a big(?) concern. I am new to Ruby as

[#30539] RDoc Alpha-6 available — Dave Thomas <Dave@...>

37 messages 2002/01/07

[#30737] rpkg 0.1 (long) — Massimiliano Mirra <list@...>

<yaaawn>

16 messages 2002/01/10

[#30866] Dir.entries have no home — Ron Jeffries <ronjeffries@...>

Chet and I were writing a little code manager yesterday and we wrote

38 messages 2002/01/11

[#30920] MetaRuby : RubySchema.rb howto? — Tobias Reif <tobiasreif@...>

Hi,

15 messages 2002/01/11
[#30953] Re: MetaRuby : RubySchema.rb howto? — Mathieu Bouchard <matju@...> 2002/01/12

[#30969] Re: MetaRuby : RubySchema.rb howto? — Tobias Reif <tobiasreif@...> 2002/01/12

Mathieu Bouchard wrote:

[#30949] Another suggestion for FreeRIDE — ptkwt@...1.aracnet.com (Phil Tomson)

Based on some discussions over at comp.lang.python...

13 messages 2002/01/12

[#31017] Why I think Ruby will eventually be more popular than Python — gandy@... (Thomas Gandy)

Ruby and Python both play in the same niche: they're both Object

9 messages 2002/01/12

[#31080] Best way for platf. independent compression? — Massimiliano Mirra <list@...>

Currently, rpkg builds packets by tar'ring and gzip'ping the source

25 messages 2002/01/13
[#31112] Re: Best way for platf. independent compression? — Chris Gehlker <gehlker@...> 2002/01/14

On 1/13/02 1:42 PM, "Massimiliano Mirra" <list@chromatic-harp.com> wrote:

[#31153] Re: Best way for platf. independent compression? — Massimiliano Mirra <list@...> 2002/01/14

On Mon, Jan 14, 2002 at 12:08:58PM +0900, Chris Gehlker wrote:

[#31085] Small Methods - a ramble — Ron Jeffries <ronjeffries@...>

I noticed in some code that Chet and I were writing that, as Smalltalkers, we tend to write really

45 messages 2002/01/13
[#31170] Re: Small Methods - a ramble — Brian Marick <marick@...> 2002/01/14

Ron Jeffries wrote:

[#31099] a wishlist for ruby 2.0 — Mathieu Bouchard <matju@...>

49 messages 2002/01/14
[#31237] Re: a wishlist for ruby 2.0 — matz@... (Yukihiro Matsumoto) 2002/01/15

Hi,

[#31276] Re: a wishlist for ruby 2.0 — Mathieu Bouchard <matju@...> 2002/01/15

[#31251] Swig Ruby documentation mods. — Hugh Sasse Staff Elec Eng <hgs@...>

I have been trying to use Swig Ruby recently, and in attempting to

10 messages 2002/01/15

[#31262] grabbing stuff from web pages — Ron Jeffries <ronjeffries@...>

Part of my web site has recommended books. I use the cover jpegs from

11 messages 2002/01/15

[#31275] how to get all the reserved words? — Tobias Reif <tobiasreif@...>

Hi;

16 messages 2002/01/15

[#31289] memory usage question — "Mark Hahn" <mchahn@...>

I need to write a script that will use a hash with 4 million strings of 16

30 messages 2002/01/15

[#31311] Vote for Windows Installer packages — Andrew Hunt <andy@...>

14 messages 2002/01/15

[#31404] Re: A question on Ruby Threads — "Tobias DiPasquale" <anany@...>

In article <a242re$gop@ftp.ee.vill.edu>, "Chris Gehlker"

15 messages 2002/01/16

[#31424] A few words on threads — "Avdi B. Grimm" <avdi@...>

Warning: many strong personal opinions and broad

14 messages 2002/01/16

[#31442] #59 Add fsync method to IO class — hensleyl@... (Leslie Hensley)

Adding fsync and fdatasync methods to the IO class will allow Ruby to

17 messages 2002/01/16

[#31512] Hello! Array sub classing? — Markt <markt@...>

Hello Ruby lovers!

23 messages 2002/01/17

[#31533] Possible bug in Mac version? — Dave Thomas <Dave@...>

16 messages 2002/01/17

[#31564] The first alternative RDoc template — Dave Thomas <Dave@...>

22 messages 2002/01/17

[#31658] dynamic method creation — "Albert L. Wagner" <alwagner@...>

I have a need to dynamically create methods with method names

16 messages 2002/01/18

[#31711] Re: zip on Linux — "Mirabai Neumann" <webmaster@...>

19 messages 2002/01/19

[#31727] Keeping track of multiple Ruby discussion sites. — "James Britt (rubydev)" <james@...>

Recently, Massimiliano Mirra wrote:

13 messages 2002/01/19

[#31735] installing mod_ruby --> seg fault in ruby-rdtool — craig@...

At least that's where core dumped. FreeBSD/Alpha (4.4-RELEASE). New to

16 messages 2002/01/19

[#31741] $_ as default parameter for a function — thomass@... (Thomas)

I'd like the fragment below to produce "blah blah", but it doesn't

15 messages 2002/01/19

[#31882] RANT: Ruby GUI API — Sean Russell <ser@...>

I started this rant in another thread, where it was way OT, so I'm moving

60 messages 2002/01/21

[#31937] Re: RANT: Ruby GUI API — Ben Crowell <crowell02@...>

M. Mirra wrote:

28 messages 2002/01/22
[#31948] Re: RANT: Ruby GUI API — John Carter <john.carter@...> 2002/01/22

On Tue, 22 Jan 2002, Ben Crowell wrote:

[#32056] Ruby Publishing Framework v0.5.0 — Bryan Murphy <bryan@...>

Ruby Publishing Framework

15 messages 2002/01/22

[#32106] about time for seperate lists? — "Tobias DiPasquale" <anany@...>

Hi all,

12 messages 2002/01/23

[#32121] : ruby-talk seperation — "Tobias DiPasquale" <anany@...>

Hi all,

19 messages 2002/01/23

[#32177] — Eugene Scripnik <Eugene.Scripnik@...>

I have a problem loading files from my script (I mean Kernel::load):

20 messages 2002/01/23
[#32187] — nobu.nokada@... 2002/01/23

Hi,

[#32722] Re: — Eugene Scripnik <Eugene.Scripnik@...> 2002/01/29

Hello nobu,

[#32728] Re: — nobu.nokada@... 2002/01/29

Hi,

[#32793] Re[2]: — Eugene Scripnik <Eugene.Scripnik@...> 2002/01/30

Tuesday, January 29, 2002, 5:05:05 PM, you wrote:

[#32799] $: in mod_ruby — nobu.nokada@... 2002/01/30

Hi,

[#32957] Re: $: in mod_ruby — Eugene Scripnik <Eugene.Scripnik@...> 2002/02/01

Wednesday, January 30, 2002, 4:55:23 PM, you wrote:

[#32233] Subclassing vs Subtyping (partly OOP vs FP) — Robert Feldt <feldt@...>

Hi,

16 messages 2002/01/24
[#33032] Re: Subclassing vs Subtyping (partly OOP vs FP) — Dave Thomas <Dave@...> 2002/02/03

Lewis Perin <perin@panix.com> writes:

[#32247] Array.last Weirdness — Jesse Jones <jesjones@...>

I'd expect the following code:

19 messages 2002/01/24

[#32312] Serious Array Bug in Ruby 1.6.6? — William Djaja Tjokroaminata <billtj@...>

Hi,

42 messages 2002/01/24
[#32315] Re: Serious Array Bug in Ruby 1.6.6? — David Alan Black <dblack@...> 2002/01/24

Hello --

[#32400] Re: Serious Array Bug in Ruby 1.6.6? — billtj@... (Bill Tj) 2002/01/25

Hi,

[#32404] Re: Serious Array Bug in Ruby 1.6.6? — David Alan Black <dblack@...> 2002/01/25

Hello --

[#32319] looking for an example problem to demonstrate TaskMaster — ptkwt@...1.aracnet.com (Phil Tomson)

I'm looking for suggestions here...

19 messages 2002/01/24

[#32355] RDoc learns to draw pictures... — Dave Thomas <Dave@...>

15 messages 2002/01/25
[#32377] Re: [ANN] RDoc learns to draw pictures... — "Pit Capitain" <pit@...> 2002/01/25

On 25 Jan 2002, at 9:34, Dave Thomas wrote:

[#32388] Ruby Developers Guide — Robert Feldt <feldt@...>

Hi,

16 messages 2002/01/25

[#32401] Sourcecode dump? — Olivier CARRERE <carrere@...>

Hello,

12 messages 2002/01/25

[#32417] Subrange of String subclass => invalid object — "Bob Alexander" <bobalex@...>

Given these conditions:

52 messages 2002/01/25

[#32445] "friend" alternative in Ruby? — kturing@... (kate turing)

I have a class "Foo". It has a method "doSecretStuff" that I want to

13 messages 2002/01/26

[#32465] rubyzip 0.3.1 — thomass@... (Thomas)

rubyzip 0.3.1 is out.

18 messages 2002/01/26

[#32593] OT: tools for creating documentation — ptkwt@...1.aracnet.com (Phil Tomson)

I'm going to be creating a good bit of documentation for TaskMaster and I

12 messages 2002/01/27

[#32646] popen3 and buffering — Paul Brannan <paul@...>

I have a program test.rb:

26 messages 2002/01/28

strangeness on solaris : SystemVIPC

From: ahoward@... (ara howard)
Date: 2002-01-23 00:32:57 UTC
List: ruby-talk #32068
obviously this works:

class Ok 

    def initialize
        method
    end

    def method
        puts "works"  

ok = Ok.new >> "works"

however, i have a slightly more compilcated senario:


some code in a class that delegates to Array and uses SystemVIPC...

class stuff...

def initialize
    
	@rows    = []

	super @rows	# my delegate	

	# try to load from memory first...
	load_rows
    
 	... some more code ...    
end

    
def load_rows
    
    begin
    	first_row = SharedMemory.new MINIMUMSIZE
    rescue => err
	# do NOT propagate this err
    	# just bomb out since there was no shmemory to be had
	puts "NO INDEX WAS FOUND, A NEW ONE WIL BE CREATED LATER"
    	return
    end

 ... more code...
end

when running on solaris i get:

sysv.rb:562:in `puts': String#to_ary should return Array (TypeError)
        from sysv.rb:562:in `load_rows'
        from sysv.rb:539:in `initialize'
        from sysv.rb:884:in `new'
        from sysv.rb:884:in `catalouge'
        from sysv.rb:928


something weird is going on but i am unsure of the nature of the
error!

notes:
	* runs perfectly on linux
	* utilizes sysvipc.so from raa
	* utilizes delegation
	* commenting OUT the call to SharedMemory.new
 	  gets the script PAST that point, so that's the problem!?

the SharedMemory.new call is the first time the interpreter has seen a
call to the class - and things get haywire after that.  any ideas as
to what KIND of problem in sysvipc.so might cause the interpreter to
freak out like that is much appreciated!

thanks

ara

ahoward@fsl.noaa.gov

i have tried cutting EVERYTHING possible thing out before


+++++++++++++++++++++++++++ COMPLETE SOURCE FOLLOWS ++++++++++++

+	run program with progname file0 file1 file2 etc..

+	obviously requires sysvipc from raa

+	program loads a bunch of files to shm and catalogs them into an
index so
	c and c++ programs can find them later

+	driver is at the bottom

SOURCE+++++++++++++++++++++++++++++++++++

require 'delegate'		# ruby built-in
require 'net/http'		# ruby built-in

begin
	require 'sysvipc'		# download from
http://deisui.bug.org/~ueno/ruby/sysvipc.html
rescue
	puts "YOU APPEAR NOT TO HAVE THE 'sysvipc' MODULE ON YOUR SYSTEM"
	puts "DOWNLOAD IT FROM http://deisui.bug.org/~ueno/ruby/sysvipc.html"
	raise
end


include FileTest



# some methods for pretty printing, and c/c++ compatibility
class String

	COLORS = { 'clear'      => 0,
			   'reset'      => 0,
			   'bold'       => 1,
			   'dark'       => 2,
			   'underline'  => 4,
			   'underscore' => 4,
			   'blink'      => 5,
			   'reverse'    => 7,
			   'concealed'  => 8,

			   'black'      => 30,   'on_black'   => 40, 
			   'red'        => 31,   'on_red'     => 41, 
			   'green'      => 32,   'on_green'   => 42, 
			   'yellow'     => 33,   'on_yellow'  => 43, 
			   'blue'       => 34,   'on_blue'    => 44, 
			   'magenta'    => 35,   'on_magenta' => 45, 
			   'cyan'       => 36,   'on_cyan'    => 46, 
			   'white'      => 37,   'on_white'   => 47 }

	EOS   = "\e[0m"

	def method_missing(method_id)
		op = method_id.id2name
		
		String.color self, op 
	end

	def String.color(s, ops)
		seq = ops.collect{|op| "\e[#{COLORS[op.downcase]}m"}
		seq.to_s + s + EOS
	end

	# eats spaces AND NULS, usefull
	def cstrip!
		strip!
		delete! "\0"
	end

	# eats spaces AND NULS, usefull
	def cstrip
		copy = self
		copy.cstrip!
		copy
	end

private
	def opstring(s)
		'\e[' + COLORS[s.downcase] + 'm'
	end
end



# class Catalouge, a view of the entire system : files and index
class Catalouge
    
    	KEY      = 7777
    	PERM     = 0744
    	CREATE   = SystemVIPC::IPC_CREAT
    	ATTACH   = ~CREATE
    	PERMMASK = 0b0000_0001_1111_1111	# the last nine bits
    	NULL     = "\0"
    
    
    
    # this class represents things to load to memory: files, db
tables, etc.
    # currently only handles files, and http gets
    class BackingStore
    
    
    	FILE     = 'file'
    	HTTP     = 'http'
    	DBMS     = 'dbms'
    
    	SEP      = ':'
    
    	PROTOCOL = %r{^[ ]*( #{FILE} | #{HTTP} | #{DBMS} )( #{SEP} )( .*
)$}iox
    	URL      = %r{^[ ]* http : // ( [^/]+ ) (/* .*) $}iox
    
    	HTTPPORT = 80
    
    	SEED     = 7
    
    	attr_reader :path, :protocol, :sep, :uri
    
    private
    	def initialize( uri )
    
    		@uri = uri
    
    		# try to parse out info from the uri - which may be just a file
name
    		m = PROTOCOL.match @uri
    		whole_match, @protocol, @sep, @path = m[0,4] if m

			@protocol = FILE unless @protocol
			@sep      = SEP  unless @sep
			@path     = @uri unless @path
		
			mtime	
    	end
    
    	def wget( uri )
    		m = URL.match uri
    				
    		raise "COULD NOT GROK URL" unless m
    
    		site, url = m[1,2]
    
    		url = '/index.html' unless url
    
    		# connect to web server
    		begin
    			http_getter = Net::HTTP.new(site, HTTPPORT)
    		rescue => err
    			p err
    			raise "COULD NOT CONNECT TO #{site}"
    		end
    
    		# grab url
    		begin
    			resp, source = http_getter.get url, nil
    		rescue => err
    			p err
    			raise "NO RESPONSE FOR URL #{url}"
    		end
    
    		source
    	end
    
    public
    	def gen_key
    		return SystemVIPC::ftok(@path, SEED) if @protocol == FILE 
    		return @path.hash
    	end
    
    	def size
    		return @data.length if @data
			return data.length 
    	end

		def to_s
			@path
		end


		def data
			return @data if @data

			begin
    			@data = 
    					if(@protocol == FILE)
    
    						(IO.readlines path).join if exists? @path and file? @path
    
    					elsif(@protocol == HTTP)
    
    						wget @uri
    
    					else	# assume it's a file

    						(IO.readlines @path).join if exists? @path and file? @path
    
    					end
    		rescue => err
    			p err
    			raise "COULD NOT RETRIEVE #{uri} VIA PROTOCOL #{@protocol}"
			end

			@mtime = nil
			mtime

			@data
		end

		def mtime    
			return @mtime if @mtime

    		begin
    			@mtime = 
    					if(@protocol == FILE)
    
							stats  = File.stat @path
							@mtime =  [stats.atime,stats.ctime,stats.mtime].max.to_i
    
    					elsif(@protocol == HTTP)
    
    						@mtime =  Time.now.to_i					# seconds since epoch 
    
    					else	# assume it's a file
    
							stats  = File.stat @path
							@mtime =  [stats.atime,stats.ctime,stats.mtime].max.to_i
    					end
    		rescue => err
    			p err
    			raise "COULD NOT GET MTIME FOR #{uri}"
    		end
	
			@mtime
		end

		def key    
			return @key if @key

    		begin
    			@key =	
    					if(@protocol == FILE)
    
    						SystemVIPC::ftok(@path, SEED)
    
    					else
    
    						@path.hash
    					end
    		rescue => err
    			p err
    			raise "COULD NOT GENERATE KEY FOR #{uri}"
    		end

			@key
		end

		def buffer
			data
		end

    end # class BackingStore
    
    
    
    # a class representing a read/write locking *SINGLE* semaphore
    # just the easy stuff
    class Semaphore
    
    	# do NOT change this number!  this class werks as a *SINGLE*
Semaphore, not a set
    	NSEMS      = 1		
    
    	MAXREADERS = 64
    
    	WRITEDEC   = [ SystemVIPC::SemaphoreOperation.new(0, -MAXREADERS
) ]
    	WRITEINC   = [ SystemVIPC::SemaphoreOperation.new(0, +MAXREADERS
) ]
    	READDEC    = [ SystemVIPC::SemaphoreOperation.new(0, -1         
) ]
    	READINC    = [ SystemVIPC::SemaphoreOperation.new(0, +1         
) ]
    
    	DEFAULTS   = Hash[ 
    						'nsems'  => NSEMS, 
    						'key'    => KEY,  
    						'perm'   => PERM, 
    						'flags'  => ATTACH,
    						'mode'   => PERM & ATTACH,
    	]
    
    
    private
    	def initialize( args = nil ) 
    
    		@args = args
    
    		DEFAULTS.each{|k,v| @args[k] = v unless @args.key? k}
    
    		mode = 
    				if(@args['flags'] == ATTACH)
    					(@args['perm']) & (ATTACH)
    				else
    					(@args['perm']) | (@args['flags'])
    				end
    
    		begin
    			@sem = SystemVIPC::Semaphore.new @args['key'], @args['nsems'],
mode
    		rescue => err
    			p err
    			raise "COULD NOT ALLOCATE SEMAPHORE"
    		end
    
    		@sem.set_value 0, MAXREADERS 
    	end
    
    
    public
    
    	def read_lock    
    		begin
    			@sem.apply READDEC  
    		rescue => err
    			p err
    			raise "COULD NOT OBTAIN READ LOCK!"
    		end
    	end
    
    	def read_unlock  
    		begin
    			@sem.apply READINC  
    		rescue => err
    			p err
    			raise "COULD NOT RELEASE WRITE LOCK!"
    		end
    	end
    
    	def write_lock   
    		begin
    			@sem.apply WRITEDEC 
    		rescue => err
    			p err
    			raise "COULD NOT OBTAIN WRITE LOCK!"
    		end
    
    	end
    
    	def write_unlock 
    		begin
    			@sem.apply WRITEINC 
    		rescue => err
    			p err
    			raise "COULD NOT RELEASE WRITE LOCK!"
    		end
    	end
    
    	def remove
    		@sem.remove if @sem
    	end
    
    end # class Semaphore
    
    
    
    # easy interface to sharedmemory
    class SharedMemory < DelegateClass( SystemVIPC::SharedMemory )
    
    	SIZE           = 2 ** 20 	# 1 MB
    
    	UPLOADATTEMPTS = 32
    
    	DEFAULTS       = Hash[ 
    							'size'   => SIZE,
    							'key'    => KEY, 
    							'perm'   => PERM,
    							'flags'  => ATTACH,
    							#'mode'   => PERM & ATTACH,
    							'locked' => true,
    	]
    
    
    private
    
    	def initialize( args = nil ) 
    
    		@args = args
    
    		@shm = @sem = nil
    
    		DEFAULTS.each{|k,v| @args[k] = v unless @args.key? k}
    
    		mode = 
    				if(@args['flags'] == ATTACH)
    					(@args['perm']) & (ATTACH)
    				else
    					(@args['perm']) | (@args['flags'])
    				end
    
    
    		@shm  = SystemVIPC::SharedMemory.new @args['key'],
@args['size'], mode
    
    		@sem  = Semaphore.new @args if( @args['locked'] or
@args['locked'] )
    
    		super @shm
    
    		@data = read if @args['flags'] == ATTACH 
    	end
    
    public
    
    	def SharedMemory.upload( backing_store, 
    	                         mode = PERM | CREATE, 
    							 locked = false )  
    
    		shm = sem = nil
    
    		key  = backing_store.gen_key
    		size = backing_store.size
    
    		attempts = UPLOADATTEMPTS

    		begin
    			shm  = SystemVIPC::SharedMemory.new key, size, mode
    		rescue => err
    			p err

    			if(--attempts > 0)
    				key += rand(1024)
					puts "TRYING TO UPLOAD #{bs.path} AGAIN WITH KEY,SIZE,MODE
#{[key,size,mode].join ','}"
    				retry
    			end

    			raise "COULD NOT GET MEMORY EVEN AFTER TRYING #{UPLOADATTEMPTS}
RANDOM KEYS?!"
    		end
    
    		begin
    			shm.attach
    			shm.write backing_store.data 
    			shm.detach
    		rescue => err
    			p err
    			raise "COULD NOT WRITE TO MEMORY"
    		end
    
    		#puts "UPLOADED #{backing_store.path} TO MEMORY"
    
    		return [backing_store.path, key, size, mode,
backing_store.mtime]
    	end
    

		#ROWCOLS      = %w( shmname   key shmsize shmflags  shmtime )

    	def SharedMemory.delete( row, locked = false )  

    		key  = row.key
    		size = row.shmsize
			mode = row.shmflags
    
    		begin
    			shm  = SystemVIPC::SharedMemory.new key, size, mode
    		rescue => err
    			p err
    			raise "COULD NOT LOCATE #{row.shmname}!" 
    		end
    
    		begin
    			shm.remove
    		rescue => err
    			p err
    			raise "COULD NOT DELETE #{row.shmname}!" 
    		end
    
    		#puts "DELETED #{row.shmname} FROM MEMORY"
    
    		return row 
    	end

    
    	def [](idx)
    		@data[idx]
    	end
    
    # these need to be made a little safer!
    	def write( buf )
    		locked = attached = false
    		begin
    			@sem.write_lock if @sem
    			locked = true
    			attach
    			attached = true
    			super
    			@data = buf
    		rescue => err
    			p err
    			raise "WRITE FAILED"
    		ensure
    			detach if attached
    			@sem.write_unlock if @sem and locked
    		end
    	end
    
    	def read( len = nil )
    		locked = attached = false
    		begin
    			@sem.read_lock if @sem
    			locked = true
    			attach
    			attached = true
    			(len) ? super(len) : super()
    		rescue => err
    			p err
    			raise "WRITE FAILED"
    		ensure
    			detach if attached
    			@sem.read_unlock if @sem and locked
    		end
    	end
    
    	def remove
    		@shm.remove if @shm
    		@sem.remove if @sem
    	end
    
    end # class SharedMemory
    
    
    
    
    # a list of all the files in the catalouge
    class Index  < DelegateClass(Array) 
    	#include SystemVIPC, if you don't want to say
SystemVIPC::var_name
    
    	WIDTH         = 2 ** 8
    	HEIGHT        = 2 ** 12 
    
    	MINROWS       = 2					# one each for the header and footer
    	MAXROWS       = HEIGHT - MINROWS 
    
    	HEADERMSG     = 'HEADER'
    	FOOTERMSG     = 'FOOTER'
    
    	MINIMUMSIZE	  = Hash[ 'size' => WIDTH]
    	CREATEMODE    = Hash['flags' => CREATE]
    
    	DIV           = ("=" * 120 + "\n").bold.red
    	LINE          = ("-" * 120 + "\n").bold.blue

		DEFAULTHEADER = [HEADERMSG, WIDTH, HEIGHT, WIDTH * HEIGHT, 2]
		DEFAULTFOOTER = [FOOTERMSG, WIDTH, HEIGHT, WIDTH * HEIGHT, 2]
    
    private
    	def initialize
    
    		@rows    = []

			# i'll be delegating any unknown methods to the @rows Array
    		super @rows		

			# try to load from memory first...
    		load_rows
    
    		if(length == 0) 		# there were no rows to load from memory!	
    			@header = Row.new DEFAULTHEADER
    			@footer = Row.new DEFAULTFOOTER 
    		else
				# we loaded some rows from memory, including the header and footer
    			# dump the header and footer so we can use @rows as a stack
    			@header = shift
    			@footer = pop
   				
				validate
    		end
    	end

    
    	def load_rows
    
    		begin
    			first_row = SharedMemory.new MINIMUMSIZE
    		rescue => err
				# do NOT propagate this err
    			# just bomb out since there was no shmemory to be had
				puts "NO INDEX WAS FOUND, A NEW ONE WIL BE CREATED"
    			return
    		end
    

			# grab the first row, which should contain header info
    		header = Row.new_from_binary first_row.read 


			# awwwwww freak out! iff the header does not look to be in decent
shape
			raise "POSSIBLE CORRUPT INDEX (HEADER MISSING)!" unless 
				header.headermsg[HEADERMSG] and
				header.width == WIDTH       and
				header.nrows < MAXROWS
    

			# having the header, we can determine the true size of the entire
index
			# and re-attach at this new size
    		@shm = SharedMemory.new Hash.new 'size' => header.indexsize
    
			# note that we don't need to read in the entire index (indexsize)
			# only that which was used 
    		buf = @shm.read header.used_bytes 
    
    		0.step(buf.length - 1, WIDTH){|o| push Row.new_from_binary
buf[o,WIDTH] }
    	end


		def validate
    			raise "POSSIBLE CORRUPT INDEX (HEADER MISSING)!" unless
@header[0][HEADERMSG]
    			raise "POSSIBLE CORRUPT INDEX (FOOTER MISSING)!" unless
@footer[0][FOOTERMSG]


    			raise "POSSIBLE CORRUPT INDEX (HEADER == FOOTER)!" unless 
					@header[1...@header.length] == @footer[1...@footer.length]
		end
    
    
    public
    
    	def to_s
    		titles = Row::HEADERCOLS.collect{|c| c.upcase}
    		cols   = Row::COLS.collect{|c| c.upcase}
    		#sprintf Row::FORMAT, titles[0], titles[1], titles[2],
titles[3], titles[4] +
    		#p titles
    
    		buf = "\n\n"
    		buf << DIV 
    		buf << sprintf(Row::HEADERFORMAT, titles[0], titles[1],
titles[2], titles[3], titles[4]).cyan
    		buf << LINE 
    		buf << @header.to_header_s
    		buf << "\n"
    		buf << DIV 
    		buf << sprintf(Row::HEADERFORMAT, cols[0], cols[1], cols[2],
cols[3], cols[4]).cyan
    		buf << LINE 
    		buf << "\n"
    		buf << @rows.to_s.yellow.bold
    		buf << "\n"
    		buf << DIV
    		titles[0][HEADERMSG] = FOOTERMSG
    		buf << sprintf(Row::HEADERFORMAT, titles[0], titles[1],
titles[2], titles[3], titles[4]).cyan
    		buf << LINE 
    		buf << @footer.to_footer_s
    		buf << "\n\n"
    	end
    
    	def remove
    		@shm.remove if @shm
    	end
    
    
    	def add_row( r, packed = false )
    		row = Row.new(r, packed)
    
    		return if @rows and index row	# do not allow duplicate entries
    
    		push row
    
    		@header.nrows = @header.nrows + 1
    
    		raise "MAXIMUM NUMBER OF ROWS EXCEEDED!" if @header.nrows >
MAXROWS
    	end
    

    	def drop_row( row )
    		raise "MINIMUM NUMBER OF ROWS EXCEEDED!" if @header.nrows - 1 <
MINROWS
    
			raise "DELETION OF NON EXISTENT ROW ATTEMPTED" unless
				@rows.delete row

    		@header.nrows = @header.nrows - 1
    	end
    
    
    	# an implementation for coarse-grained persistence via shared
memory
    	# if the machine crashes this will not persist - but regenerate
instead
    
    	def sync
    
    		#puts "IN SYNC @rows has #{@rows.length} entries"
    
    		begin
    			# grab some memory if we don't already have any
				puts "CREATING A NEW INDEX IN MEMORY" unless @shm
    			@shm = SharedMemory.new CREATEMODE    unless @shm 
    		rescue => err
    			p err
    			raise "COULD NOT ALLOCATED MEMORY FOR A NEW INDEX"
    		end
    
    		sort! if @rows
    		uniq! if @rows
    
    		# check here that nrows is correct!!
    
    		raise "CORRUPT HEADER OR INDEX!" if @header.nrows !=
@rows.length + 2

			#HACK

			@footer[1...@footer.length] = @header[1...@header.length] 
    
    		buf = @header.packed
    
    		@rows.each{ |row| buf += row.packed } if @rows
    
    		buf += @footer.packed 
    
    		begin
    			@shm.write buf 
    		rescue => err
    			p err
    			raise "COULD NOT WRITE TO MEMORY!"
    		end
    	end
    
    	alias persist sync			# you may call it either way
    
    
    
    
   
    	def has_entry_for?(bs)
    		each do |row| 
    			return row if row.shmname.cstrip == bs.path
    		end	
    		return nil 
    	end
    
    	# this only handles files right now!!, needs to handle bs's
    	def is_stale?(bs)
    		

		entry = has_entry_for? bs

			
		return entry if entry and entry.shmtime < bs.mtime 
		return nil
  			
    	end
    
    end #class Index
    
	class Row < DelegateClass(Array) 

		HEADERCOLS   = %w( headermsg width height  indexsize nrows )
		ROWCOLS      = %w( shmname   key shmsize shmflags  shmtime )

		COLS         = %w( shmname   key shmsize shmflags  shmtime )


		TEMPLATE     = 'a240NNNN'		# 240 bytes followed by 4 network order 4
byte ints
		PACKED       = true
		NOTPACKED    = false 

		NONNULLHEAD  = %r{[/^[^ \0]*/]}
		SPACE        = %r{\s}
		NULLPAT      = %r{\0}
		NUMBER       = %r{^ *\d+ *$}

		NULL         = "\0"

		#FORMAT       = "%-32.32s%16d%16d%16d%16d\n"
		FORMAT       = "%-32.32s%16s%16s%16s%16s\n"
		HEADERFORMAT = "%-32.32s%16.16s%16.16s%16.16s%16.16s\n"


	private

		def initialize(r, packed = NOTPACKED)

			if(r.instance_of? String) 
				if(packed)
					@cols = r.unpack TEMPLATE
				else
					@cols = r.split SPACE, COLS.length
				end
			elsif(r.instance_of? Array)
				@cols = r[0...COLS.length]
			else
				raise "MUST INITIALIZE WITH AN ARRAY OR STRING!"	
			end

			# turn anything that looks like a number into one
			@cols.collect!{ |c| c =~ NUMBER ? c.to_i : c } 


			super( @cols )
		end

	public
		def Row.new_from_binary(r)
			Row.new r, PACKED
		end

		def packed
			pack TEMPLATE
		end

		# this allows access by the names in COLS
		# eg. row.shmsize, row.shmsize = 4096, row.width, etc.
		# gives functions : headermsg, width, height, indexsize nrows
		# gives functions : shmname, key, shmsize, shmflags, shmtime

		def method_missing(method_id, *args)
			name = method_id.id2name

			setter = name['=']	# am i a setter method?
			name.delete! '=' 

			idx = (COLS.index name or HEADERCOLS.index name)

			self[idx] = args[0] if setter and idx
			self[idx] if idx
		end

		def used_bytes
			width * nrows 
		end

		def <=>(other)		
			return self[0].strip.delete(NULL) <=> other[0].strip.delete(NULL)
if other.is_a? Row
			return self[0].strip.delete(NULL) <=> other.strip.delete(NULL)   
if other.is_a? String
		end

		def ==(other)
		#puts "comparing #{self.join ' '} to #{other}"
		#caller 
			return self[0].strip.delete(NULL) == other[0].strip.delete(NULL) if
other.is_a? Row
			return self[0].strip.delete(NULL) == other.strip.delete(NULL)    if
other.is_a? String
			#self.size                 == other.size and
			#self.time                 == other.time
		end


		def to_s
			sprintf FORMAT, self[0].delete(NULL), 
							"0x" + sprintf("%x",self[1]), 
							self[2].to_s, 
							#self[3].to_s, 
							#self[3].to_s, 
							"0" + sprintf("%o", self[3] & PERMMASK),
							#self[4].to_s
							"\t" + Time.at(self[4]).to_s
		end

		def to_header_s
			sprintf FORMAT, self[0].delete(NULL), 
							self[1].to_s,  
							self[2].to_s, 
							self[3].to_s,
							self[4].to_s
			
		end

		alias to_footer_s to_header_s
	end #class Row
    
    
    
    
public
	# this is the main program, if you will
	def catalouge(uris)
        # test code
       




		

        @index = Index.new

		backingstores = uris.collect{ |uri| BackingStore.new uri }


		backingstores.each do |bs|

			if(entry = @index.has_entry_for? bs)

				if(entry.shmtime < bs.mtime)
					@index.drop_row SharedMemory.delete entry 
					@index.add_row  SharedMemory.upload bs	
					
					
				end
			else				# there is NO entry - upload
				@index.add_row SharedMemory.upload bs	

				
			end
		end

        
		begin
			@index.sync
		rescue
			raise "CATALOUGING FAILED, COULD NOT SYNC INDEX!"
		end
	end


	def to_s
		@index.to_s
	end

end #class Catalouge




legitimate_files = ARGV.collect{|arg| (exists? arg and file? arg) ?
arg : nil}.compact

catalouge = Catalouge.new

catalouge.catalouge legitimate_files

print catalouge

__END__

In This Thread

Prev Next