[jcifs] Patch: Support for LARGE_READX and LARGE_WRITEX

Thomas Krammer TKrammer at nxn-software.com
Wed Jan 29 04:40:52 EST 2003


Hi,

I updated jCIFS 0.7.1 to support the LARGE_READX and LARGE_WRITEX
capabilities. This results in an increased download speed (in my tests the
speed was more than doubled) when dealing with a Windows 2000 server.
When I connected to a Samba server the code didn't show a similar speedup
because the negotiated buffer size already is 64k (4k on Windows).

Client: Windows 2000 Pro Java 1.4.1_01
Server: Windows 2000 Pro

Transferred data: 51.5 MB file

Download:
  jCIFS 0.7.1:        3316kB/s
  modified version:   6993kB/s
  cmd /c copy:        7941kB/s

Upload:
  jCIFS 0.7.1:        2137kB/s
  modified version:   2646kB/s
  cmd /c copy:        5450kB/s

The reported values are the average of 5 runs of the same test.

Some notes:

1) I used ethereal to look at the SMB packages created by Windows 2000. It
seems the native Window 2000 SMB client uses 0xF000 as maximum buffer size.
So I restricted the buffer size to that value.
2) Currently I don't know why the upload doesn't similar benefit from the
increased buffer size as the download.
3) To benefit from the increased read/write buffer size the caller should
use buffers > 4kB in calls to SmbFileInputStream.read() and
SmbFileOutputStream.write(). To collect the performance data above I used
32kB buffers.
4) The supplied patch is against my modified version and not against the
orginal jCIFS 0.7.1 code. So you may have to apply the patch I recently sent
to this mailing list (support for files >4GB) first.

The code:

*** jcifs_0.7.1\src\jcifs\smb\SmbFileOutputStream.java	Mon Jan 27 18:51:38
2003
--- jcifs_0.7.1_mod\src\jcifs\smb\SmbFileOutputStream.java	Tue Jan 28
15:16:00 2003
***************
*** 33,38 ****
--- 33,39 ----
      private SmbFile file;
      private boolean append;
      private int openFlags, writeSize;
+     private int writeSizeFile;
      private long fp;
      private byte[] tmp = new byte[1];
  
***************
*** 107,114 ****
--- 108,124 ----
              }
          }
          file.open( openFlags );
+ 
          writeSize = Math.min( file.tree.session.transport.snd_buf_size -
70,
 
file.tree.session.transport.server.maxBufferSize - 70 );
+         
+
if(file.tree.session.transport.hasCapability(ServerMessageBlock.CAP_LARGE_WR
ITEX)) {
+             // Server supports LARGE_WRITEX.
+             // The request's size may exceed the negotiated buffer size. 
+             writeSizeFile =
Math.min(file.tree.session.transport.snd_buf_size - 70, 0xF000);
+         } else {
+             writeSizeFile = writeSize;
+         }
      }
  
  /**
***************
*** 165,175 ****
              }
          }
  
          Log.println( Log.WARNINGS, "smb write warning",
                          " fid=" + file.fid + ",off=" + off + ",len=" + len
);
          int w;
          do {
!             w = len > writeSize ? writeSize : len;
              file.send( new SmbComWriteAndX( file.fid, fp, len - w, b, off,
w, null ),
                                                          new
SmbComWriteAndXResponse() );
              fp += w;
--- 175,188 ----
              }
          }
  
+         // Only enable large blocks for disk files.
+         int blockSize = (file.getType() == SmbFile.TYPE_FILESYSTEM) ?
writeSizeFile : writeSize;
+         
          Log.println( Log.WARNINGS, "smb write warning",
                          " fid=" + file.fid + ",off=" + off + ",len=" + len
);
          int w;
          do {
!             w = len > blockSize ? blockSize : len;
              file.send( new SmbComWriteAndX( file.fid, fp, len - w, b, off,
w, null ),
                                                          new
SmbComWriteAndXResponse() );
              fp += w;

*** jcifs_0.7.1\src\jcifs\smb\SmbFileInputStream.java	Wed Jan 15 21:56:44
2003
--- jcifs_0.7.1_mod\src\jcifs\smb\SmbFileInputStream.java	Tue Jan 28
15:15:51 2003
***************
*** 33,38 ****
--- 33,39 ----
      private SmbFile file;
      private long fp;
      private int off, readSize, openFlags;
+     private int readSizeFile;
      private byte[] tmp = new byte[1];
  
  /**
***************
*** 67,74 ****
--- 68,84 ----
          this.file = file;
          this.openFlags = openFlags;
          file.open( openFlags );
+ 
          readSize = Math.min( file.tree.session.transport.rcv_buf_size -
70,
 
file.tree.session.transport.server.maxBufferSize - 70 );
+         
+
if(file.tree.session.transport.hasCapability(ServerMessageBlock.CAP_LARGE_RE
ADX)) {
+             // Server supports LARGE_READX.
+             // The request's size may exceed the negotiated buffer size. 
+             readSizeFile =
Math.min(file.tree.session.transport.rcv_buf_size - 70, 0xF000);
+         } else {
+             readSizeFile = readSize;
+         }
      }
  
  /**
***************
*** 133,141 ****
              response.responseTimeout = 0;
          }
  
          int r, n;
          do {
!             r = len > readSize ? readSize : len;
  //System.out.println( "len=" + len + ",r=" + r + ",fp=" + fp );
              try {
                  file.send( new SmbComReadAndX( file.fid, fp, r, null ),
response );
--- 143,154 ----
              response.responseTimeout = 0;
          }
  
+         // Only enable large blocks for disk files.
+         int blockSize = (file.getType() == SmbFile.TYPE_FILESYSTEM) ?
readSizeFile : readSize;
+         
          int r, n;
          do {
!             r = len > blockSize ? blockSize : len;
  //System.out.println( "len=" + len + ",r=" + r + ",fp=" + fp );
              try {
                  file.send( new SmbComReadAndX( file.fid, fp, r, null ),
response );

*** jcifs_0.7.1\src\jcifs\smb\SmbTransport.java	Wed Jan 15 21:56:44 2003
--- jcifs_0.7.1_mod\src\jcifs\smb\SmbTransport.java	Tue Jan 28 15:18:36
2003
***************
*** 42,48 ****
      private static final int DEFAULT_SO_TIMEOUT    = 15000;
      private static final int PUSHBACK_BUF_SIZE     = 64;
      private static final int DEFAULT_RCV_BUF_SIZE  = 60416;
!     private static final int DEFAULT_SND_BUF_SIZE  = 5000;
  
      static final int MID_OFFSET      = 30;
      static final int HEADER_LENGTH   = 32;
--- 42,48 ----
      private static final int DEFAULT_SO_TIMEOUT    = 15000;
      private static final int PUSHBACK_BUF_SIZE     = 64;
      private static final int DEFAULT_RCV_BUF_SIZE  = 60416;
!     private static final int DEFAULT_SND_BUF_SIZE  = 60416;
  
      static final int MID_OFFSET      = 30;
      static final int HEADER_LENGTH   = 32;
***************
*** 93,99 ****
                  ServerMessageBlock.FLAGS2_LONG_FILENAMES |
 
ServerMessageBlock.FLAGS2_UNICODE );
          int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
!                 ServerMessageBlock.CAP_UNICODE |
ServerMessageBlock.CAP_NT_SMBS );
          String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
                  System.getProperty( "os.name" ));
          String nativeLanMan = Config.getProperty(
"jcifs.smb.client.nativeLanMan", "jCIFS" );
--- 93,100 ----
                  ServerMessageBlock.FLAGS2_LONG_FILENAMES |
 
ServerMessageBlock.FLAGS2_UNICODE );
          int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
!                 ServerMessageBlock.CAP_UNICODE |
ServerMessageBlock.CAP_NT_SMBS | 
!                 ServerMessageBlock.CAP_LARGE_READX |
ServerMessageBlock.CAP_LARGE_WRITEX);
          String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
                  System.getProperty( "os.name" ));
          String nativeLanMan = Config.getProperty(
"jcifs.smb.client.nativeLanMan", "jCIFS" );

*** jcifs_0.7.1\src\jcifs\smb\ServerMessageBlock.java	Wed Jan 15 21:56:44
2003
--- jcifs_0.7.1_mod\src\jcifs\smb\ServerMessageBlock.java	Mon Jan 27
20:08:35 2003
***************
*** 60,65 ****
--- 60,67 ----
      static final int CAP_LOCK_AND_READ    = 0x0100;
      static final int CAP_NT_FIND          = 0x0200;
      static final int CAP_DFS              = 0x1000;
+     static final int CAP_LARGE_READX      = 0x4000;
+     static final int CAP_LARGE_WRITEX     = 0x8000;
  
      // file attribute encoding
      static final int ATTR_READONLY   = 0x01;


More information about the jcifs mailing list