Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Finding, if file is used exclusively
Message
 
 
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Divers
Thread ID:
00425134
Message ID:
00425505
Vues:
15
Thanks for the code, Houston. I'll include it in our program library.

>No kudos, when you have to reply to your own message :-(
>
>IF cActualDbf # cTable = ".DBF"
>
>Should read IF cActualDbf = cTable + ".DBF"
>
>And the example invocation should read
> IF EMPTY( fUse( ..... ))

>
>>>>>This can fail. Another user can grab the table between the RETURN and USE EXCLUSIVE. I'm not saying it will, but the possibility is there.
>>>>
>>>>You could reduce the probability of this by an incredibly small amount by doing the close and return at the same time:
RETURN fh > 0 AND FCLOSE(fh)
This way the close does not happen until the very last moment. And because VFP evaluates expressions from left to right and there is an AND, if the file was not opened then the FCLOSE() will not be attempted.
>>>
>>>That does reduce the time between them, but still leaves open the possibility that someone else will grab the file.
>>
>>Actually, I normally open all tables (in any mode) using a UDF, which traps the failure to open the file. Even if Nadya's process is successful opening the table exclusively, it sounds like there is a possibility that a different process (or User) could then encounter an error trying to open the table shared. Consequently, I recommend the solution proposed in Barbara's initial response (error trapping).
>>
>>For Nadya, this is an outline of a UDF and it's call - note that it does not cover all permutations of table, alias, open mode, and path (specifically it does not cover situations where you have two tables with the same name in different paths) - there are no compile error messages, but that does not mean much in VFP :-)
IF fUse( "MyTable", "EXCLUSIVE", "Path", "Alias", "Order", etc. )
>>   *- Ok to PACK, rebuild Indexes, etc.
>>ELSE
>>   *- Inform User if interactive, or write to log file if batch (unattended).
>>ENDIF
>>
>>#DEFINE CURRENT_LOCK_STATUS    2011
>>#DEFINE DEFAULT_ERROR_HANDLER  DO SysError WITH ERROR(), MESSAGE(), etc.
>>
>>*****************************************************
>>FUNCTION fUse( cTable, cMode, cPath, cAlias, cOrder )
>>*****************************************************
>>   *- cTable is the only mandatory parameter, all others are optional.
>>
>>   *- cMode : If specified MUST be one of "SHARED" or "EXCLUSIVE", defaults to "SHARED".
>>   *- cPath : Relative, Aabsolute, or UNC.
>>   *- cAlias : Self explanatory.
>>   *- cOrder : Index tag name.
>>
>>   *- Returns empty string if successful, otherwise returns an error message, which
>>   *- always begins with "ERROR: fUse() "
>>
>>   *- To increase the robustness of this function, all of the parameters
>>   *- should be checked for correct data type (if passed in).
>>
>>   LOCAL cActualDbf, cOpenResult, cCurrentLockStatus, cUseArguments
>>   IF EMPTY( cTable )
>>      *- If running unattended then this might be the ideal point to record
>>      *- failure to a log file.
>>      RETURN "ERROR: fUse() cTable not specified."
>>   ENDIF
>>   IF EMPTY( cMode )
>>   	*- Assign default value,
>>   	cMode = "SHARED"
>>   ENDIF
>>   IF USED( cTable )
>>      *- Table is already open.
>>      IF NOT EMPTY( cAlias ) AND USED( cAlias )
>>      	*- Dang! Table is open and alias is also in use. So close both and
>>      	*- re-open table with the desired alias.
>>      	USE IN (cTable)
>>      	USE IN (cAlias)
>>      ELSE
>>      	*- Table is open and alias has not been specified, so do not need
>>      	*- to do anything further.
>>      	SELECT (cTable)
>>      	RETURN ""
>>      ENDIF
>>   ENDIF
>>   IF NOT EMPTY( cAlias ) AND USED( cAlias )
>>      *- Alias has been specifed but is already in use, so verify that table
>>      *- is correct - since it is possible that the table might be other than
>>      *- the one specified in cTable.
>>      cActualDbf = DBF( cAlias )
>>      cActualDbf = SUBSTR( cActualDbf, RAT( "\", cActualDbf ) + 1 )
>>      IF cActualDbf # cTable = ".DBF"
>>         *- Table is already open with the desired alias, but what about cMode?
>>         SELECT (cAlias)
>>         IF EMPTY( cMode )
>>            *- Do not need to do anything else.
>>            RETURN ""
>>         ELSE
>>            *- Determine mode that the table is currently opened with.
>>            cCurrentLockStatus = UPPER( SYS( CURRENT_LOCK_STATUS )) == "EXCLUSIVE"
>>            IF cCurrentLockStatus = cMode
>>            	*- Do not need to do anything.
>>            	RETURN ""
>>            ENDIF
>>            *- cMode is not the same as the cCurrentLockStatus, so need to close and
>>            *- re-open the table with the desired cMode.
>>            USE IN (cAlias)
>>         ENDIF
>>      ELSE
>>         *- Need to close cAlias and open cTable
>>         USE IN (cAlias)
>>      ENDIF
>>   ELSE
>>   	*- Either the alias was not specified, or it is not currently in use,
>>   	*- either way nothing needs to happen here, so this ELSE code could be
>>   	*- deleted.
>>   ENDIF
>>
>>   *- To get here, either the table is not already open, or if it was open it has
>>   *- been closed because either the cAlias was incorrect or the cMode.
>>
>>   *- Fabricate USE arguments.
>>   IF NOT EMPTY( cPath )
>>   	cPath = ADDBS( cPath )
>>   ENDIF
>>   cUseArguments = IIF( NOT EMPTY( cPath ), cPath, "" ) ;
>>                  + cTable ;
>>                  + IIF( NOT EMPTY( cAlias ), " AS " + cAlias, "" ) ;
>>                  + " " + cMode ;
>>                  + " IN 0"
>>   cOpenResult = ""
>>   ON ERROR cOpenResult = "ERROR: fUse() " + MESSAGE()
>>   USE &cUseArguments.
>>   *- Restore default error handler.
>>   ON ERROR DEFAULT_ERROR_HANDLER
>>
>>   IF EMPTY( cOpenResult )
>>      *- Table was opened sucessfully.
>>      IF EMPTY( cAlias )
>>         SELECT (cTable)
>>   	ELSE
>>   	   SELECT (cAlias)
>>   	ENDIF
>>   	IF NOT EMPTY( cOrder )
>>   		SET ORDER TO (cOrder)
>>   	ENDIF
>>   ENDIF
>>   RETURN cOpenResult
>>   ENDFUNC  && fUse( cTable, cMode, cPath, cAlias, cOrder ).
>>
If it's not broken, fix it until it is.


My Blog
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform