You may meet intermittent error when running DotNetFile adapter in SDK on multiple host instances to access a remote file share.

You may meet intermittent error when running DotNetFile adapter in SDK on multiple host instances to access a remote file share.

The DotNetFile adapter in SDK has a different behavior to process 0 byte files than the built-in File adapter (0 byte files will be deleted directly by File adapter). Therefore, sometimes we will need to use this adapter for 0 byte file processing. However, you may meet intermittent error like below when running DotNetFile adapter in SDK on multiple host instances to access a remote file share.

This is because the file hander is owned by other process immediately when an adapter instance is trying to delete or rename the file. To fix the error, we have to add some 'Retry logic' in the adapter code when deleting or renaming files and add Guid to temp file names.

 

Below are the modified code snippets:

 

privatevoid PickupFilesAndSubmit ()

        {

           

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] PickupFilesAndSubmit called");

           

           

 

int maxBatchSize = this.properties.MaximumBatchSize;

           

 

int maxNumberOfFiles = this.properties.MaximumNumberOfFiles;

           

 

List<BatchMessage> files = newList<BatchMessage>();

           

 

long bytesInBatch = 0;

           

 

DirectoryInfo di = newDirectoryInfo(this.properties.Directory);

           

 

FileInfo[] items = di.GetFiles(this.properties.FileMask);

           

           

 

//Trace.WriteLine(string.Format("[DotNetFileReceiverEndpoint] Found {0} files.", items.Length));

           

 

foreach (FileInfo item in items)

            {

               

 

// only consider files that are not read only

               

 

if (FileAttributes.ReadOnly == (FileAttributes.ReadOnly & item.Attributes))

                   

 

continue;

               

 

// only download files that are less than the configured max file size

               

 

if (false == CheckMaxFileSize(item))

                   

 

continue;

               

 

string fileName = Path.Combine(properties.Directory, item.Name);

               

 

//if (fileName.Contains("BTS-WIP"))

               

 

// System.Diagnostics.EventLog.WriteEntry("CCMS Adapter", "File Name: " + fileName);

               

 

string renamedFileName;

               

 

if ( this.properties.WorkInProgress.Length > 0 )

                    renamedFileName = fileName +

 

this.properties.WorkInProgress + System.Guid.NewGuid().ToString();

               

 

else

                    renamedFileName =

 

null;

               

 

// If we couldn't lock the file, just move onto the next file

               

 

IBaseMessage msg = CreateMessage(fileName, renamedFileName);

               

 

if ( null == msg )

                   

 

continue;

               

 

if ( null == renamedFileName )

                    files.Add(

 

newBatchMessage(msg, fileName, BatchOperationType.Submit));

               

 

else

                    files.Add(

 

newBatchMessage(msg, renamedFileName, BatchOperationType.Submit));

               

 

// keep a running total for the current batch

                bytesInBatch += item.Length;

               

 

// zero for the value means infinite

               

 

bool fileCountExceeded = ((0 != maxNumberOfFiles) && (files.Count >= maxNumberOfFiles));

               

 

bool byteCountExceeded = ((0 != maxBatchSize) && (bytesInBatch > maxBatchSize));

               

 

if (fileCountExceeded || byteCountExceeded)

                {

                   

 

// check if we have been asked to stop - if so don't start another batch

                   

 

if (this.controlledTermination.TerminateCalled)

                       

 

return;

                   

 

// execute the batch

                    SubmitFiles(files);

                   

 

// reset the running totals

                    bytesInBatch = 0;

                    files.Clear();

                }

            }

 

 

      

 

privateIBaseMessage CreateMessage (string srcFilePath, string renamedFileName)

        {

           

 

Stream fs;

           

 

bool renamed = false;

           

 

// Open the file

           

 

try

            {

               

 

if (!String.IsNullOrEmpty(renamedFileName))

                {

                   

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] Renaming file " + srcFilePath);

                   

 

File.Move(srcFilePath, renamedFileName);

                   

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] Renaming file Done " + renamedFileName);

                    renamed =

 

true;

                   

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] Opening file " + renamedFileName);

                    fs =

 

File.Open(renamedFileName, FileMode.Open, FileAccess.Read, FileShare.None);

                   

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] Opening file Done " + renamedFileName);

                }

               

 

else

                {

                    fs =

 

File.Open(srcFilePath, FileMode.Open, FileAccess.Read, FileShare.None);

                }

            }

           

 

catch(Exception)

            {

               

 

// If we renamed the file, rename it back

               

               

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] Error occured. Renamed: " + renamed + " Renamed File Name: " + renamedFileName);

               

 

if (renamed)

                {

                   

                 

 

// Trace.WriteLine("[DotNetFileReceiverEndpoint] On error renaming file back " + renamedFileName);

                   

                   

 

bool bRenameBack = false;

                   

 

int bRetryCount = 0;

                   

 

while (!bRenameBack && bRetryCount < 1000)

                    {

                       

 

try

                        {

                           

 

File.Move(renamedFileName, srcFilePath);

                   

 

// Trace.WriteLine("[DotNetFileReceiverEndpoint] On error renaming file back Done " + renamedFileName);

                        }

                       

 

catch (Exception)

                        {

                     

 

// Trace.WriteLine("[DotNetFileReceiverEndpoint] On error renaming file back Failed " + renamedFileName);

                            System.Threading.

 

Thread.Sleep(10);

                            bRetryCount++;

                        }                       

                    }

                }               

               

 

returnnull;

            }

 

 

 

          

 

internalvoid OnBatchComplete(bool overallStatus)

            {

               

 

//Trace.WriteLine(string.Format("[DotNetFileReceiverEndpoint] OnBatchComplete called. overallStatus == {0}.", overallStatus));

               

 

if (overallStatus == true) //Batch completed

                {

                   

 

//Delete the files

                   

 

foreach (BatchMessage batchMessage in messages)

                    {

                       

 

//Close the stream so we can delete this file

                        batchMessage.Message.BodyPart.Data.Close();

                       

 

bool bDeleted = false;

                       

 

int bRetryCount = 0;

                       

 

while (!bDeleted && bRetryCount < 1000000 )

                        {

                           

 

try

                            {

                               

 

File.Delete((string)batchMessage.UserData);

                                bDeleted =

 

true;

                            }

                           

 

catch (Exception ex)

                            {

                               

 

//Trace.WriteLine("[DotNetFileReceiverEndpoint] {0}", ex.Message);

                                System.Threading.

 

Thread.Sleep(10);

                                bRetryCount++;

                            }

                        }

                    }

                }

            }

 

 

Best regards,

WenJun Zhang