Class: Readorder::Results

Inherits:
Object
  • Object
show all
Defined in:
lib/readorder/results.rb

Overview

Results persists the results from a readorder run The results are persisted in an SQlite3 database which allows for ordering the results by whatever means are wanted.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, batch_size = 1) ⇒ Results

:call-seq:

Results.new( filename, 10_000 ) -> results

Create a new Results object with a batch size. The batch size is how many items to queue up to run in a single transaction into the sqlite database.

By default the batch size is 1 which is not very performant.



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/readorder/results.rb', line 36

def initialize( filename, batch_size = 1 )
  @db = Amalgalite::Database.new( filename )

  unless @db.schema.tables['readorder_valid'] then
    logger.info "Creating tables"
    @db.execute_batch( Results.create_table_sql )
  end
  @db.reload_schema!
  @batch_size = batch_size
  @valid_queue = []
  @error_queue = []
end

Class Method Details

.create_table_sqlObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/readorder/results.rb', line 8

def self.create_table_sql
  sql = <<-SQL
    CREATE TABLE readorder_valid ( 
       original_order              INTEGER PRIMARY KEY NOT NULL,
       size                        INTEGER NOT NULL,
       inode_number                INTEGER NOT NULL UNIQUE,
       first_physical_block_number INTEGER UNIQUE,
       physical_block_count        INTEGER,
       filename                    TEXT    NOT NULL UNIQUE
    );

    CREATE TABLE readorder_errors (
       original_order              INTEGER PRIMARY KEY NOT NULL,
       filename                    TEXT NOT NULL UNIQUE,
       error_reason                TEXT NOT NULL
    );
  SQL
end

Instance Method Details

#add_datum(datum) ⇒ Object

:call-seq:

results.add_datum( datum )

add a datum to the database, this will insert the datum into either valid or errors depending on the state of datum.valid?



80
81
82
83
84
85
86
87
# File 'lib/readorder/results.rb', line 80

def add_datum( datum )
  if datum.valid?
    @valid_queue << datum
  else
    @error_queue << datum
  end
  flush if ((@valid_queue.size + @error_queue.size) >= @batch_size )
end

#closeObject



49
50
51
52
# File 'lib/readorder/results.rb', line 49

def close
  flush
  @db.close
end

#each_error(&block) ⇒ Object

:call-seq:

results.each_error { |e| ... }

Return each error record without any predefined order



217
218
219
220
221
# File 'lib/readorder/results.rb', line 217

def each_error( &block )
  @db.execute( "SELECT * FROM readorder_errors" ) do |row|
    yield row
  end
end

#each_valid(&block) ⇒ Object

:call-seq:

results.each_valid { |v| ... }

Return each valid record without any predefined order



139
140
141
142
143
# File 'lib/readorder/results.rb', line 139

def each_valid( &block )
  @db.execute( "SELECT * FROM readorder_valid" ) do |row|
    yield row
  end
end

#each_valid_by_field(field, &block) ⇒ Object

:call-seq:

results.each_valid_by_field( field ) { |v| ... }


171
172
173
174
175
# File 'lib/readorder/results.rb', line 171

def each_valid_by_field( field, &block )
  @db.execute( "SELECT * from readorder_valid ORDER BY #{field} ASC" ) do |row|
    yield row
  end
end

#each_valid_by_first_physical_block_number(&block) ⇒ Object

:call-seq:

results.each_valid_by_physical_block_number { |v| ... }

Return each valid record in physical block number order



151
152
153
154
155
# File 'lib/readorder/results.rb', line 151

def each_valid_by_first_physical_block_number( &block )
  each_valid_by_field( 'first_physical_block_number' ) do |row|
    block.call( row )
  end
end

#each_valid_by_inode_number(&block) ⇒ Object

:call-seq:

results.each_valid_by_inode_number { |v| ... }


161
162
163
164
165
# File 'lib/readorder/results.rb', line 161

def each_valid_by_inode_number( &block )
  each_valid_by_field( 'inode_number' ) do |row|
    block.call( row )
  end
end

#error_countObject

:call-seq:

results.error_count -> Integer

return the number of errors



207
208
209
# File 'lib/readorder/results.rb', line 207

def error_count
  @db.first_value_from( "SELECT count(original_order) FROM readorder_errors" )
end

#flushObject



54
55
56
57
# File 'lib/readorder/results.rb', line 54

def flush
  flush_valid
  flush_error
end

#flush_errorObject

:call-seq:

results.flush_error

Flush all the error items to disk



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/readorder/results.rb', line 182

def flush_error
  if @error_queue.size > 0 then
    logger.info "Flushing #{@error_queue.size} error items to disk"
    sql = <<-insert
    INSERT INTO readorder_errors ( original_order, filename, error_reason )
    VALUES( ?, ?, ? );
    insert
    @db.transaction do |trans|
      trans.prepare( sql ) do |stmt|
        until @error_queue.empty? do
          datum = @error_queue.shift
          stmt.execute( datum.original_order, 
                        datum.filename,
                        datum.error_reason  )
        end
      end
    end
  end
end

#flush_validObject

:call-seq:

results.flush_valid

Flush all the pending valid items to the sqlite database



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/readorder/results.rb', line 95

def flush_valid
  if @valid_queue.size > 0 then
    logger.info "Flushing #{@valid_queue.size} valid items to disk"
    sql = <<-insert
    INSERT INTO readorder_valid ( original_order, 
                                  size,
                                  inode_number,
                                  first_physical_block_number,
                                  physical_block_count,
                                  filename )
    VALUES( ?, ?, ?, ?, ?, ? );
    insert
    @db.transaction do |trans|
      trans.prepare( sql ) do |stmt|
        until @valid_queue.empty? do
          datum = @valid_queue.shift
          stmt.execute( datum.original_order,
                        datum.size,
                        datum.inode_number,
                        datum.first_physical_block_number,
                        datum.physical_block_count,
                        datum.filename)
        end
      end
    end
  end
end

#has_datum_for_filename?(filename) ⇒ Boolean

:call-seq:

results.has_datum_for_filename?( filename )

return true or false if the give filename is alread in the database

Returns:

  • (Boolean)


69
70
71
# File 'lib/readorder/results.rb', line 69

def has_datum_for_filename?( filename )
  @db.first_value_from( "SELECT filename FROM readorder_valid WHERE filename = ?", filename )
end

#loggerObject



59
60
61
# File 'lib/readorder/results.rb', line 59

def logger
  Logging::Logger[ self ]
end

#valid_countObject

:call-seq:

results.valid_count -> Integer

return the number of valid result rows



128
129
130
# File 'lib/readorder/results.rb', line 128

def valid_count
  @db.first_value_from( "SELECT count(original_order) FROM readorder_valid" )
end