Class: PEROBS::StackFile

Inherits:
Object
  • Object
show all
Defined in:
lib/perobs/StackFile.rb

Overview

This class implements a file based stack. All entries must have the same size.

Instance Method Summary collapse

Constructor Details

#initialize(dir, name, entry_bytes) ⇒ StackFile

Create a new stack file in the given directory with the given file name.

Parameters:

  • dir (String)

    Directory

  • name (String)

    File name

  • entry_bytes (Integer)

    Number of bytes each entry must have



40
41
42
43
44
# File 'lib/perobs/StackFile.rb', line 40

def initialize(dir, name, entry_bytes)
  @file_name = File.join(dir, name + '.stack')
  @entry_bytes = entry_bytes
  @f = nil
end

Instance Method Details

#clearObject

Remove all entries from the stack.



117
118
119
120
# File 'lib/perobs/StackFile.rb', line 117

def clear
  @f.truncate(0)
  @f.flush
end

#closeObject

Close the stack file. This method must be called before the program is terminated to avoid data loss.



64
65
66
67
68
69
70
71
72
# File 'lib/perobs/StackFile.rb', line 64

def close
  begin
    @f.flush
    @f.flock(File::LOCK_UN)
    @f.close
  rescue IOError => e
    PEROBS.log.fatal "Cannot close stack file #{@file_name}: #{e.message}"
  end
end

#eachObject

Iterate over all entries in the stack and call the given block for the bytes.



124
125
126
127
128
129
# File 'lib/perobs/StackFile.rb', line 124

def each
  @f.seek(0)
  while !@f.eof
    yield(@f.read(@entry_bytes))
  end
end

#openObject

Open the stack file.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/perobs/StackFile.rb', line 47

def open
  begin
    if File.exist?(@file_name)
      @f = File.open(@file_name, 'rb+')
    else
      @f = File.open(@file_name, 'wb+')
    end
  rescue => e
    PEROBS.log.fatal "Cannot open stack file #{@file_name}: #{e.message}"
  end
  unless @f.flock(File::LOCK_NB | File::LOCK_EX)
    PEROBS.log.fatal 'Database stack file is locked by another process'
  end
end

#popString or nil

Pop the last entry from the stack file.

Returns:

  • (String or nil)

    Popped entry or nil if stack is already empty.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/perobs/StackFile.rb', line 100

def pop
  begin
    return nil if @f.size == 0

    @f.seek(-@entry_bytes, IO::SEEK_END)
    bytes = @f.read(@entry_bytes)
    @f.truncate(@f.size - @entry_bytes)
    @f.flush
  rescue => e
    PEROBS.log.fatal "Cannot pop from stack file #{@file_name}: " +
      e.message
  end

  bytes
end

#push(bytes) ⇒ Object

Push the given bytes onto the stack file.

Parameters:

  • bytes (String)

    Bytes to write.



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/perobs/StackFile.rb', line 85

def push(bytes)
  if bytes.length != @entry_bytes
    PEROBS.log.fatal "All stack entries must be #{@entry_bytes} " +
      "long. This entry is #{bytes.length} bytes long."
  end
  begin
    @f.seek(0, IO::SEEK_END)
    @f.write(bytes)
  rescue => e
    PEROBS.log.fatal "Cannot push to stack file #{@file_name}: #{e.message}"
  end
end

#syncObject

Flush out unwritten data to file.



75
76
77
78
79
80
81
# File 'lib/perobs/StackFile.rb', line 75

def sync
  begin
    @f.flush
  rescue IOError => e
    PEROBS.log.fatal "Cannot sync stack file #{@file_name}: #{e.message}"
  end
end

#to_aryArray

Return the content of the stack as an Array.

Returns:



133
134
135
136
137
# File 'lib/perobs/StackFile.rb', line 133

def to_ary
  a = []
  each { |bytes| a << bytes }
  a
end