# 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.

## 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.

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