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
60
# 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, max_in_memory / 2,
                                     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.



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

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.



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

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:



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

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:



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

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:



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

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.



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

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.



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

def page_count
  @page_counter
end

#save_page(p) ⇒ Object

Save the given IDListPage into the cache file.

Parameters:



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

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