borderAndreaVB free resources for Visual Basic developersborder

borderAndreaVB Visual Basic and VB.NET source code resources - Copyright © 1999-2008 Andrea Tincaniborder

AndreaVB | Forum | News | Downloads | Register | Help | Member List | Statistics | Search | PM | Profile

Print This Topic
Next Topic (Report Help...) New Topic New Poll Post Reply
AndreaVB Forum : VB General : Gracefully Handling Multiple Users Accessing the Same File Simultaneously
Poster Message
matt_1ca
Level: Scholar

Registered: 27-03-2005
Posts: 46

icon Gracefully Handling Multiple Users Accessing the Same File Simultaneously

I found out the hard way that when many users are trying
to do run an OpenTextFile statement on the same file at
the same time then some users will get the
"Permission Denied" error.

In order to solve the problem what I did was write a function
like the one below which tries to test if a file is currently
being open and being read or written to by another person.

I have put line numbers here just for ease in referring to
portions of the program.

10 Function IsReadyToOpen(strFileName As String) As Boolean

20 Dim blnIsReady As Boolean, fle As New FileSystemObject
30 Dim tst As TextStream

40 On Error GoTo errHand

50 blnIsReady = True

60 Set tst = fle.OpenTextFile(strFileName, ForReading, False)
70 tst.Close
80 Set tst = Nothing
90 Set fle = Nothing

'''no permission denial everything went as expected

100 IsReadyToOpen = blnIsReady

110 Exit Function

120 errHand:

'''permission is being denied

130 blnIsReady = False
140 IsReadyToOpen = blnIsReady

150 Set fle = Nothing

160 End Function

I am concerned that I might inadvertently corrupt
file or lose data due to this function and want it to be as
programming tight as possible.

You will notice this as the heart of the routine that if the
function issues the OpenTextfile and it fails then it will set the
return value to false in line 130-140 then just set fle to nothing

I am not so comfortable with not closing a file before setting
fle to nothing. But the problem I have is what will happen if I
try to issue a tst.close in a line say 145. I am not too sure how
that will work... first an error in opening has made the execution
jump to this point and if the said tst.close in 145 causes yet
another execution error already from within the error handle then
will that leave me in a crash on top of data loss or file corruption?

In other words how do I execute this thing as gracefully as possible
making sure that files are properly closed and fle set to nothing?

I would be open to any ideas in case anybody knows of any technique
that will allow me to know if a file is already open without actually
issuing an OpenTextFile method ... such a technique would be safer
I think.

Thanks you so much for all the kind help you can give.

Matt

01-02-2008 at 01:37 PM
View Profile Send Email to User Show All Posts | Quote Reply
stickleprojects
Level: Moderator


Registered: 09-09-2002
Posts: 997
icon Re: Gracefully Handling Multiple Users Accessing the Same File Simultaneously

Hi,
You should use openfile, then capture the error gracefully.
To maximise the number of users that can use a file, get a local copy of it (either in memory or on disk).
If you need to support concurrent updates of the file consider using a database -it's free.

You should open the file, read it, then close it.
for example (assuming the file already exists):
on error resume next

Set tst = fle.OpenTextFile(strFileName, ForReading, False)
if err=0 then
   mybuffer = tst.readall
   blnAllRead = true
else
   mybuffer = ""
   blnAllRead = false
end if
tst.Close
Set tst = Nothing

(


The method you have will work, however, there is a (small) time delay between "Isreadytoopen" and reading the file, so do it all in one go.

If you need to allow updative access (ie. "lock" the file whilst someone is "updating" it), you could use this class. Paste it into a class module:



Option Explicit

Private m_LockFileHandle As Integer

Public Enum LockFileResultEnum
    Ok = -1
    Failed = 0
    LockFileInUse
    UnableToSetLockFileName
End Enum

Private m_strLockFileName As String
Private m_strLockFileContents As String

Public Property Get LockFileContents() As String
    LockFileContents = m_strLockFileContents
End Property
Private Function SetLockFileName(strFilename As String) As Boolean

    m_strLockFileName = strFilename & ".lck"
    SetLockFileName = True
    
End Function
Private Function LockFileExists() As Boolean
    If Dir$(m_strLockFileName) <> "" Then LockFileExists = True
    
End Function
Private Function DeleteLockFile() As Boolean
    
    If LockFileExists() Then
        
        On Error Resume Next
        Kill m_strLockFileName
        If LockFileExists() = False Then DeleteLockFile = True
    Else
        DeleteLockFile = True
    End If
End Function
Public Function LockFile(strFilename As String, Optional strLockText As String) As LockFileResultEnum
    Dim lngRet As LockFileResultEnum
      
    On Error GoTo errh
    
    If m_LockFileHandle <> -1 Then
        Err.Raise -1, "LockFile", "Lock already in use, use ReleaseLock to release lock"
        GoTo exith
    End If
    
    If SetLockFileName() Then
    
        ' Kill the file - it may be there if the client crashed
        If DeleteLockFile() = False Then
        
            ' Read the locking info
            Dim fin As Integer
            fin = FreeFile
            Open m_LockFileName For Input As fin
            m_strLockTextFound = Input(LOF(fin), fin)
            Close fin
            
            lngRet = LockFileInUse
        Else
            ' Lock file doesn't exist, so let's create one AND KEEP IT OPEN!!!
            m_LockFileHandle = FreeFile
            Open m_LockFileName For Output As fout
            Print #m_LockFileHandle, strLockText
            
            lngRet = Ok
        End If
        
        
    Else
        lngRet = UnableToSetLockFileName
        
    End If
    
    LockFile = lngRet
    
exith:
    On Error GoTo 0
    Exit Function

errh:
    Screen.MousePointer = vbDefault
    Err.Raise Err.Number, Err.Source & ",Project1.clsMyFileLock.LockFile", Err.Description
    
End Function

Public Sub ReleaseLock()
    On Error Resume Next
    If m_LockFileHandle <> 0 Then Close m_LockFileHandle
    
    If Err = 0 Then
        m_LockFileHandle = -1
        m_strLockFileContents = ""
        m_strLockFileName = ""
    End If
    
End Sub

Private Sub Class_Initialize()
    m_LockFileHandle = -1
    m_strLockFileContents = ""
    m_strLockFileName = ""
    
End Sub

Private Sub Class_Terminate()
    ' Release the lock
    ReleaseLock
        
End Sub



The class will release the lock when it is destroyed.
The reason why I hold the file handle, is so that the operating system implements the locking and stops someone else zapping the file.

to use:
create an instance of this class for the duration of the lock
then call LockFile(strfilename,"some text here") and check the return value.
If the lock fails (ie. doesn't = True) then you can check the lockfilecontents to see what was in the lockfile
I use the lockfile to hold the user's name, what they were doing, all that sort of thing (incidentally, I write an xml fragment so I can hold lots more info).
this class is limited to one person, but you could extend it to allow read-access but single writeaccess (see msaccess ldb file)


Hope this helps,
Kieron



[Edited by stickleprojects on 06-02-2008 at 08:22 AM GMT]

____________________________
Build it better, faster, quicker, easier.. then fix it (non-offical MS mission statement)

06-02-2008 at 08:17 AM
View Profile Send Email to User Show All Posts | Quote Reply
AndreaVB Forum : VB General : Gracefully Handling Multiple Users Accessing the Same File Simultaneously
Next Topic (Report Help...) New Topic New Poll Post Reply
Surf To:


Not Logged In? Username: Password: Lost your password?
Partners: Download Actual Software | Free Software Download
borderAndreaVB free resources for Visual Basic developersborder

borderAndreaVB Visual Basic and VB.NET source code resources - Copyright © 1999-2008 Andrea Tincaniborder