Batching

The CIFS protocol provides a mechanism for issuing several commands in a single message. This performance enhancement is called "batching" or "chaining". For example an SMB_COM_TREE_CONNECT_ANDX is often batched "inside" an SMB_COM_SESSION_SETUP_ANDX. Furthermore, an SMB_COM_QUERY_INFORMATION might be batched in the SMB_COM_TREE_CONNECT_ANDX resulting in three commands being issued to the server in one message. There are of course many more permutations that can occur.

Tuning Batched Requests

Do not change batch level properties. They are considered advanced properties and should not be changed unless instructed to do so or if you really know what your doing. Setting a batch level property may result in commands failing on one machine and not on another in mysterious ways.

This library can optimally batch any request with any other although it is prevented from doing so in accordance with the CIFS specification. The CIFS specification does not, however, specify how many commands may be batched together in a given message. Below is a list of jcifs property identifiers that may be used to tune the "batch level" a command may assume relative to it's precedent command. For example the SessionSetupAndX may be followed by a TreeConnectAndX (that is to say the TreeConnectAndX is batched in the SessionSetupAndX) as indicated by it's subcategorized placement under SessionSetupAndX in the below list.


SessionSetupAndX
	TreeConnectAndX

TreeConnectAndX
	CheckDirectory
	CreateDirectory
	Delete
	DeleteDirectory
	OpenAndX
	Rename
	Transaction
	QueryInformation

OpenAndX
	ReadAndX

NTCreateAndX
	ReadAndX

ReadAndX
	Close

WriteAndX
	ReadAndX
	Close

By default all commands are permitted to batch with their parent only one level deep. So at most only two commands may be issued in one message. To instruct jcifs to restrict a command from being batched at all or enable a command to be at most the second, third, or the Nth place command one might set a property like:
jcifs.smb.client.TreeConnectAndX.QueryInformation = 2
Batch level properties begin with jcifs.smb.client followed by one of the parent commands in the list above (AndX commands) and the command to be batched (must be listed under the the parent). The value must be an integer indicating the "batch level". The above example would instruct jcifs that the QueryInformation command may be batched with the TreeConnectAndX command only if it is the second command or less in a series of batched commands. So for example a SessionSetupAndX followed by a TreeConnectAndX followed by a QueryInformation may batch in the same message because by default the TreeConnectAndX may be the first in a series and, according to the example property above, the QueryInformation may be the second of a series, which in this case it is. If however this property read:
jcifs.smb.client.TreeConnectAndX.QueryInformation = 0
the above scenario would result in the SessionSetupAndX and TreeConnectAndX commands being issued to the server first followed by the QueryInformation by itself in a separate message. IOW the zero would specifies that QueryInformation may not be batched with TreeConnectAndX at all.

Potential Problems

Unfortunately it appears as though most(if not all) servers allow for batching on a message by message basis. Meaning it is not uniformly supported. For example NT will allow the QueryInformation to appear as the second command (double batched) of a SessionSetupAndX and TreeConnectAndX whereas Samba will only allow the single batch. It is generally assumed that all messages indicated in the CIFS specification as batchable may be single batched.

When setting these properties either in a jcifs PropertiesTree file or on the command line with the -D VM argument the full property key must be specified. Normally abbriviating properties by only specifiing a subset of the key's labels is permitted however because the last two labels of the key (e.g. TreeConnectAndX.QueryInformation) are required to appear together and because of the way keys are resolved by the PropertiesTree class, abbriviating these properties is not feasable. See the documentation on PropertiesTree for a more detailed explaination as to why.

Why Should Batching Behavior Be Changed?

Again, in all likelyhood you would not want to change these properties. However there are at least three reasons why one might want to change batching behavior. One is if a special message is manually constructed to perform a specific function and batch all messages together must be enabled. For example SessionSetupAndX, TreeConnectAndX, OpenAndX, ReadAndX, and Close might all be batched together so that a small file could be read in one message. Under certain conditions this might prove to be a huge performace benifit(if you read 100 files on 100 different servers quickly for example). However it is highly unlikely that any server would support batching to this degree.

Contrarily, it might be discovered that a particular server does not support batching in one form or another in which case it can be turned off. This can be occomplished by specifying a batch level of 0 for the errant command(s) or more easily by simply setting the jcifs.smb.client.useBatching property to false.

Another reason might be that a CIFS developer is tesing/developing a server's batching functionality. In this case it might be usefull to construct a PropertiesTree file with all command identifiers expanded in tagged format available for easy tweeking. Here is such a tagged block ready for inclusion in a PropertiesTree file with all values set to their default(single batching).


<jcifs>
    <smb>
        <client>
            <SessionSetupAndX>
                TreeConnectAndX = 1
            </SessionSetupAndX>
            <TreeConnectAndX>
                CheckDirectory = 1
                CreateDirectory = 1
                Delete = 1
                DeleteDirectory = 1
                OpenAndX = 1
                Rename = 1
                Transaction = 1
                QueryInformation = 1
            </TreeConnectAndX>
            <OpenAndX>
                ReadAndX = 1
            </OpenAndX>
            <NTCreateAndX>
                ReadAndX = 1
            </NTCreateAndX>
            <ReadAndX>
                Close = 1
            </ReadAndX>
            <WriteAndX>
                ReadAndX = 1
                Close = 1
            </WriteAndX>
        </client>
    </smb>
</jcifs>