Class: Rufio::NativeScannerRubyCore

Inherits:
Object
  • Object
show all
Defined in:
lib/rufio/native_scanner.rb

Overview

非同期スキャナークラス(Pure Ruby実装、ポーリングベース)

Constant Summary collapse

POLL_INTERVAL =

10ms

0.01

Instance Method Summary collapse

Constructor Details

#initializeNativeScannerRubyCore

Returns a new instance of NativeScannerRubyCore.



8
9
10
11
12
13
14
15
16
# File 'lib/rufio/native_scanner.rb', line 8

def initialize
  @thread = nil
  @state = :idle
  @results = []
  @error = nil
  @current_progress = 0
  @total_progress = 0
  @mutex = Mutex.new
end

Instance Method Details

#cancelObject

キャンセル



206
207
208
209
210
# File 'lib/rufio/native_scanner.rb', line 206

def cancel
  @mutex.synchronize do
    @state = :cancelled if @state == :scanning
  end
end

#closeObject

スキャナーを明示的に破棄



218
219
220
221
# File 'lib/rufio/native_scanner.rb', line 218

def close
  @thread&.join if @thread&.alive?
  @thread = nil
end

#get_progressObject

進捗取得



196
197
198
199
200
201
202
203
# File 'lib/rufio/native_scanner.rb', line 196

def get_progress
  @mutex.synchronize do
    {
      current: @current_progress,
      total: @total_progress
    }
  end
end

#get_resultsObject

結果取得(完了後)



213
214
215
# File 'lib/rufio/native_scanner.rb', line 213

def get_results
  @mutex.synchronize { @results.dup }
end

#get_stateObject

状態確認



191
192
193
# File 'lib/rufio/native_scanner.rb', line 191

def get_state
  @mutex.synchronize { @state }
end

#scan_async(path) ⇒ Object

非同期スキャン開始

Raises:

  • (StandardError)


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rufio/native_scanner.rb', line 19

def scan_async(path)
  raise StandardError, "Directory does not exist: #{path}" unless Dir.exist?(path)
  raise StandardError, "Scanner is already running" unless @state == :idle

  @mutex.synchronize do
    @state = :scanning
    @results = []
    @error = nil
    @current_progress = 0
    @total_progress = 0
  end

  @thread = Thread.new do
    begin
      # ディレクトリをスキャン
      entries = []
      Dir.foreach(path) do |entry|
        next if entry == '.' || entry == '..'

        # キャンセルチェック
        break if @state == :cancelled

        full_path = File.join(path, entry)
        stat = File.lstat(full_path)

        entries << {
          name: entry,
          type: file_type(stat),
          size: stat.size,
          mtime: stat.mtime.to_i,
          mode: stat.mode,
          executable: stat.executable?,
          hidden: entry.start_with?('.')
        }

        # 進捗を更新
        @mutex.synchronize do
          @current_progress += 1
          @total_progress = entries.length + 1
        end
      end

      # 結果を保存
      @mutex.synchronize do
        if @state == :cancelled
          @state = :cancelled
        else
          @results = entries
          @state = :done
        end
      end
    rescue StandardError => e
      @mutex.synchronize do
        @error = e
        @state = :failed
      end
    end
  end

  self
end

#scan_fast_async(path, max_entries) ⇒ Object

高速スキャン(エントリ数制限付き)

Raises:

  • (StandardError)


82
83
84
85
86
87
88
89
90
91
92
93
94
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/rufio/native_scanner.rb', line 82

def scan_fast_async(path, max_entries)
  raise StandardError, "Directory does not exist: #{path}" unless Dir.exist?(path)
  raise StandardError, "Scanner is already running" unless @state == :idle

  @mutex.synchronize do
    @state = :scanning
    @results = []
    @error = nil
    @current_progress = 0
    @total_progress = max_entries
  end

  @thread = Thread.new do
    begin
      entries = []
      count = 0

      Dir.foreach(path) do |entry|
        next if entry == '.' || entry == '..'
        break if count >= max_entries

        # キャンセルチェック
        break if @state == :cancelled

        full_path = File.join(path, entry)
        stat = File.lstat(full_path)

        entries << {
          name: entry,
          type: file_type(stat),
          size: stat.size,
          mtime: stat.mtime.to_i,
          mode: stat.mode,
          executable: stat.executable?,
          hidden: entry.start_with?('.')
        }
        count += 1

        # 進捗を更新
        @mutex.synchronize do
          @current_progress = count
        end
      end

      # 結果を保存
      @mutex.synchronize do
        if @state == :cancelled
          @state = :cancelled
        else
          @results = entries
          @state = :done
        end
      end
    rescue StandardError => e
      @mutex.synchronize do
        @error = e
        @state = :failed
      end
    end
  end

  self
end

#wait(timeout: nil) ⇒ Object

ポーリングして完了待ち



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/rufio/native_scanner.rb', line 147

def wait(timeout: nil)
  start_time = Time.now
  loop do
    state = get_state

    case state
    when :done
      return get_results
    when :failed
      raise @error || StandardError.new("Scan failed")
    when :cancelled
      raise StandardError, "Scan cancelled"
    end

    if timeout && (Time.now - start_time) > timeout
      raise StandardError, "Timeout"
    end

    sleep POLL_INTERVAL
  end
end

#wait_with_progress(&block) ⇒ Object

進捗報告付きで完了待ち



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/rufio/native_scanner.rb', line 170

def wait_with_progress(&block)
  loop do
    state = get_state
    progress = get_progress

    yield(progress[:current], progress[:total]) if block_given?

    case state
    when :done
      return get_results
    when :failed
      raise @error || StandardError.new("Scan failed")
    when :cancelled
      raise StandardError, "Scan cancelled"
    end

    sleep POLL_INTERVAL
  end
end