[Win32utils-devel] Playing with ReadFileScatter()

Park Heesob phasis at gmail.com
Tue Oct 9 10:56:41 EDT 2007


Hi,
----- Original Message ----- 
From: "Daniel Berger" <djberg96 at gmail.com>
To: "win32utils-devel" <win32utils-devel at rubyforge.org>
Sent: Tuesday, October 09, 2007 8:27 PM
Subject: [Win32utils-devel] Playing with ReadFileScatter()


> Hi all,
> 
> Looking at the IO.readlines source in io.c, it looks to me like they 
> grab 8k chunks, split on the input record separator, and buffer accordingly.
> 
> Since it looks like ReadFileScatter() does some of that work 
> automatically (in page file sized chunks), I thought I'd give it a try. 
> Here's what I've got, but it doesn't work. I have an incorrect parameter 
> in the call to ReadFileScatter(). So, I've either got the size wrong, 
> bad alignment or I need to pass in a packed data structure of some sort.
> 
> Any ideas? BTW, you'll want to grab the latest windows-pr from CVS in 
> order to run this code.
> 
> Thanks,
> 
> Dan
> 
<snip> 
Here is a complete working source using ReadFileScatter.

Notice that VirtualAlloc shoud be redifined. Since ReadFileScatter requires page 
aligned memory buffer, I allocated buffer using VirtualAlloc. 


Regards,

Park Heesob

# WinIO.readlines

require 'windows/handle'
require 'windows/error'
require 'windows/system_info'
require 'windows/nio'
require 'windows/file'
require 'windows/synchronize'
require 'windows/msvcrt/io'
require 'windows/msvcrt/buffer'
require 'windows/memory'
      
class WinIO
   extend Windows::Error
   extend Windows::Handle
   extend Windows::NIO
   extend Windows::File
   extend Windows::Synchronize
   extend Windows::MSVCRT::IO
   extend Windows::MSVCRT::Buffer
   extend Windows::SystemInfo
   extend Windows::Memory
   
   include Windows::File
   include Windows::Memory
   
   PAGE_READWRITE   =   4  
   ERROR_IO_PENDING =   997
   MEM_RELEASE      =   0x8000     

   def self.readlines(file, sep = $INPUT_RECORD_SEPARATOR)
      handle = CreateFile(
         file,
         GENERIC_READ,
         FILE_SHARE_READ,
         nil,
         OPEN_EXISTING,
         FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
         nil
      )

      if handle == INVALID_HANDLE_VALUE
         raise SystemCallError.new(GetLastError())
      end

      sysbuf = 0.chr * 40
      GetSystemInfo(sysbuf)
      page_size  = sysbuf[4,4].unpack('L')[0] # dwPageSize shoud be sysbuf[4,4] not sysbuf[8,4] 
      file_size  = File.size(file)
      page_num = (file_size*1.0 / page_size).ceil

      API.new('VirtualAlloc', 'LLLL', 'L')  # redefined VirtualAlloc

      base_address  = VirtualAlloc(nil, page_size * page_num, MEM_COMMIT, PAGE_READWRITE)
      buf_list = []
      for i in 0...page_num
        buf_list.push(base_address+page_size*i)
      end
      
      seg_array = buf_list.pack('Q*') + 0.chr * 8
      olapped = 0.chr * 20
      
      unless ReadFileScatter(handle, seg_array, page_size * page_num, nil, olapped)      
         error = GetLastError()
         if error != ERROR_IO_PENDING
           raise SystemCallError.new(error)
         end
      end
     
      sleep 0.01 unless HasOverlappedIoCompleted(olapped)

      unless CloseHandle(handle)
         raise SystemCallError.new(GetLastError())
      end

      buffer = 0.chr * file_size
      memcpy(buffer, buf_list[0], file_size)
      VirtualFree(base_address,0,MEM_RELEASE)
      
      buffer.split(sep).map {|x| x+"\n"}
   end  
end

a = IO.readlines('c:/work/java.txt')
b = WinIO.readlines('c:/work/java.txt',"\r\n")
p a==b


More information about the win32utils-devel mailing list