class Rufio::NativeScannerRubyCore

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

def cancel

キャンセル
def cancel
  @mutex.synchronize do
    @state = :cancelled if @state == :scanning
  end
end

def close

スキャナーを明示的に破棄
def close
  @thread&.join if @thread&.alive?
  @thread = nil
end

def file_type(stat)

ファイルタイプを判定
def file_type(stat)
  if stat.directory?
    'directory'
  elsif stat.symlink?
    'symlink'
  elsif stat.file?
    'file'
  else
    'other'
  end
end

def get_progress

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

def get_results

結果取得(完了後)
def get_results
  @mutex.synchronize { @results.dup }
end

def get_state

状態確認
def get_state
  @mutex.synchronize { @state }
end

def initialize

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

def scan_async(path)

非同期スキャン開始
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

def scan_fast_async(path, max_entries)

高速スキャン(エントリ数制限付き)
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

def wait(timeout: nil)

ポーリングして完了待ち
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

def wait_with_progress(&block)

進捗報告付きで完了待ち
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