Class: PEROBS::IDListPageFile

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

Overview

The IDListPageFile class provides filesystem based cache for the IDListPage objects. The IDListRecord objects only hold the index of the page in this cache. This allows the pages to be garbage collected and swapped to the file. If accessed, the pages will be swaped in again. While this process is similar to the demand paging of the OS it has absolutely nothing to do with it.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(list, dir, name, max_in_memory, page_size) ⇒ IDListPageFile

Create a new IDListPageFile object that uses the given file in the given directory as cache file.

Parameters:

  • list (IDList)

    The IDList object that caches pages here

  • dir (String)

    An existing directory

  • name (String)

    A file name (without path)

  • max_in_memory (Integer)

    Maximum number of pages to keep in memory

  • page_size (Integer)

    The number of values in each page



52
53
54
55
56
57
58
59
# File 'lib/perobs/IDListPageFile.rb', line 52

def initialize(list, dir, name, max_in_memory, page_size)
  @list = list
  @file_name = File.join(dir, name + '.cache')
  @page_size = page_size
  open
  @pages = PersistentObjectCache.new(max_in_memory, -1, IDListPage, self)
  @page_counter = 0
end

Instance Attribute Details

#page_sizeObject (readonly)

Returns the value of attribute page_size.



43
44
45
# File 'lib/perobs/IDListPageFile.rb', line 43

def page_size
  @page_size
end

#pagesObject (readonly)

Returns the value of attribute pages.



43
44
45
# File 'lib/perobs/IDListPageFile.rb', line 43

def pages
  @pages
end

Instance Method Details

#clearObject

Clear all pages, erase the cache and re-open it again.



123
124
125
126
127
128
129
130
131
132
# File 'lib/perobs/IDListPageFile.rb', line 123

def clear
  @pages.clear
  @page_counter = 0
  begin
    @f.truncate(0)
  rescue IOError => e
    raise RuntimeError, "Cannote truncate cache file #{@file_name}: " +
      e.message
  end
end

#eraseObject

Discard all pages and erase the cache file.



135
136
137
138
139
# File 'lib/perobs/IDListPageFile.rb', line 135

def erase
  @pages.clear
  @page_counter = 0
  close
end

#load(page_idx, record) ⇒ IDListPage

Load the IDListPage from the cache file.

Parameters:

  • page_idx (Integer)

    The page index in the page file

  • record (IDListPageRecord)

    the corresponding IDListPageRecord

Returns:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/perobs/IDListPageFile.rb', line 65

def load(page_idx, record)
  # The IDListPageRecord will tell us the actual number of values stored
  # in this page.
  values = []
  unless (entries = record.page_entries) == 0
    begin
      @f.seek(page_idx * @page_size * 8)
      values = @f.read(entries * 8).unpack("Q#{entries}")
    rescue IOError => e
      PEROBS.log.fatal "Cannot read cache file #{@file_name}: #{e.message}"
    end
  end

  # Create the IDListPage object with the given values.
  p = IDListPage.new(self, record, page_idx, values)
  @pages.insert(p, false)

  p
end

#mark_page_as_modified(p) ⇒ Object

Mark a page as modified. This means it has to be written into the cache before it is removed from memory.

Parameters:



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

def mark_page_as_modified(p)
  @pages.insert(p)
  @pages.flush
end

#new_page(record, values = []) ⇒ IDListPage

Create a new IDListPage and register it.

Parameters:

  • record (IDListPageRecord)

    The corresponding record.

  • values (Array of Integer) (defaults to: [])

    The values stored in the page

Returns:



94
95
96
97
98
99
# File 'lib/perobs/IDListPageFile.rb', line 94

def new_page(record, values = [])
  idx = @page_counter
  @page_counter += 1
  mark_page_as_modified(IDListPage.new(self, record, idx, values))
  idx
end

#page(record) ⇒ IDListPage

Return the IDListPage object with the given index.

Parameters:

Returns:

  • (IDListPage)

    The page corresponding to the index.



104
105
106
107
108
109
110
111
112
# File 'lib/perobs/IDListPageFile.rb', line 104

def page(record)
  p = @pages.get(record.page_idx, record) || load(record.page_idx, record)
  unless p.uid == record.page_idx
    raise RuntimeError, "Page reference mismatch. Record " +
      "#{record.page_idx} points to page #{p.uid}"
  end

  p
end

#page_countObject

Return the number of registered pages.



86
87
88
# File 'lib/perobs/IDListPageFile.rb', line 86

def page_count
  @page_counter
end

#save_page(p) ⇒ Object

Save the given IDListPage into the cache file.

Parameters:



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/perobs/IDListPageFile.rb', line 143

def save_page(p)
  if p.record.page_entries != p.values.length
    raise RuntimeError, "page_entries mismatch for node #{p.uid}"
  end
  begin
    @f.seek(p.uid * @page_size * 8)
    @f.write(p.values.pack('Q*'))
  rescue IOError => e
    PEROBS.log.fatal "Cannot write cache file #{@file_name}: #{e.message}"
  end
end