Too many times clients have run into problems with shadow databases that only seem to be fully cured by deleting the shadow and re-creating it rather then simply refreshing it in the usual ways. For one thing, refreshing does not get rid any tables in the shadow that have been deleted in the master.
Asking novice users to delete a shadow folder is asking for trouble, and without deleting it not all problems will be resolved, in my experience. Giving users access to the control panel to "create" a shadow is also not something I am fond of. Besides, creating and overwriting an existing shadow does not always get rid of whatever might be causing a problem with a shadow.
So, I have finally succeeded in creating some scripts that from the shadow will close itself, open the master, delete all the files in the the shadow folder and then re-create the shadow from scratch. This may sound easy, but if you have ever tried it you most likely found all kinds of peculiar tweaks were needed to make it work reliably and without problems (e.g., the 2 second delay in one the scripts is essential).
In addition to the two scripts that follow, I am going to attach a test database, which also has a script for making a shadow from a master (just using create_shadow2("database_name") won't work).
Ray Lyons
'Date Created: 26-Oct-2005 05:49:21 PM
'Last Updated: 19-Jan-2006 08:14:57 PM
'Created By : Ray Lyons
'Updated By : Ray Lyons
'******** Del_Re-Create Shadow script **********************************
'Addin variables to communicate with the master DB to be opened here
DIM aiv AS P
DIM aiv.DelShadow AS P
aiv = addin.variables()
dim aiv.DelShadow.Create_shadow as L
dim aiv.DelShadow.shadow_path as c
'check to see if in master or shadow.
dim Master_name as c
Master_name=a5.Get_Master_Name() 'Here just using to get shadow folder
'name and to check whether we are in
'the master (="") or the shadow.
If Master_name = ""
ui_msg_box("STOP","You are NOT in a Shadow database."+crlf(2)+"You can only run this operation from a Shadow.",UI_STOP_SYMBOL+UI_OK)
END
End if
'Routine to get shadow path to be deleted once shadow is closed & master opened.
dim shadow_folder_name as c
shadow_folder_name = file.filename_parse(Master_name,"n")
aiv.DelShadow.shadow_path = a5.Get_Path() 'path for the shadowed DB--use in autoexec when coming back
response = ui_msg_box("Shadow Path","Shadow DB Path = "+aiv.DelShadow.shadow_path+crlf(2)+"Shadow Database Name = "+Shadow_folder_name+crlf(2)+"Are you sure you want to delete and re-create Shadow Database?",UI_QUESTION_SYMBOL+UI_YES_NO)
If response = UI_NO_SELECTED
aiv.DelShadow.Create_shadow = .F. 'set fales so when master opens nothing is triggered.
end
else
'current is a shadow, so close shadow, open Master and create a
'shadow there using the aiv.DelShadow.Create_shadow as the trigger.
aiv.DelShadow.Create_shadow = .T. 'set true so when master opens code will triger
dim Master_name as c
Master_name=a5.Get_Master_Name()
Trimmed_path = alltrim(Master_Name)
:a5.load(Trimmed_path)
end if
END
'************************ END **************
'Date Created: 18-Jan-2006 02:30:01 PM
'Last Updated: 19-Jan-2006 08:36:07 PM
'Created By : Ray Lyons
'Updated By : Ray Lyons
'*******************************Autoexec script ************************
DIM aiv AS P
DIM aiv.DelShadow AS P
aiv = addin.variables()
dim aiv.DelShadow.Create_shadow as L 'Used to trigger or not.
dim aiv.DelShadow.shadow_path as c 'Used for deleting and re-creating the shadow.
dim Master_Path as c
Master_path=a5.Get_Master_Path()'If this ="", it is NOT shadowed
If aiv.DelShadow.Create_shadow = .t. .AND. Master_path = "" 'currently in the Master, so delete & create shadow
aiv.DelShadow.Create_shadow = .F. 'so shadow won't trigger this
dim success_flag as L 'indicates whether anything was removed--not using now but may
Success_Flag = DIR_REMOVE_RECURSE(aiv.DelShadow.shadow_path,.t.) '.t. suppresses warning
DIM GLOBAL pDlg1 as {waitdialog}
pDlg1.Create(1,"Message")
pDlg1.Set_Title("Please Wait")
pDlg1.Set_Message("Operation still processing.")
pDlg1.Set_Bottom_Message("Only a few seconds left.")
dim DBname as c
DBname = file.filename_parse(a5.get_name(),"N")
xbasic_wait_for_idle(2) 'Seems to need at least a 2 sec delay or A5 really gets screwed up
pDlg1.Close()
'next line is for v6 and above. Check docs for v5 version of it
create_shadow2(aiv.DelShadow.shadow_path+"\\"+DBname,.t.)
End if
END
'*************************** END *********************************
Asking novice users to delete a shadow folder is asking for trouble, and without deleting it not all problems will be resolved, in my experience. Giving users access to the control panel to "create" a shadow is also not something I am fond of. Besides, creating and overwriting an existing shadow does not always get rid of whatever might be causing a problem with a shadow.
So, I have finally succeeded in creating some scripts that from the shadow will close itself, open the master, delete all the files in the the shadow folder and then re-create the shadow from scratch. This may sound easy, but if you have ever tried it you most likely found all kinds of peculiar tweaks were needed to make it work reliably and without problems (e.g., the 2 second delay in one the scripts is essential).
In addition to the two scripts that follow, I am going to attach a test database, which also has a script for making a shadow from a master (just using create_shadow2("database_name") won't work).
Ray Lyons
'Date Created: 26-Oct-2005 05:49:21 PM
'Last Updated: 19-Jan-2006 08:14:57 PM
'Created By : Ray Lyons
'Updated By : Ray Lyons
'******** Del_Re-Create Shadow script **********************************
'Addin variables to communicate with the master DB to be opened here
DIM aiv AS P
DIM aiv.DelShadow AS P
aiv = addin.variables()
dim aiv.DelShadow.Create_shadow as L
dim aiv.DelShadow.shadow_path as c
'check to see if in master or shadow.
dim Master_name as c
Master_name=a5.Get_Master_Name() 'Here just using to get shadow folder
'name and to check whether we are in
'the master (="") or the shadow.
If Master_name = ""
ui_msg_box("STOP","You are NOT in a Shadow database."+crlf(2)+"You can only run this operation from a Shadow.",UI_STOP_SYMBOL+UI_OK)
END
End if
'Routine to get shadow path to be deleted once shadow is closed & master opened.
dim shadow_folder_name as c
shadow_folder_name = file.filename_parse(Master_name,"n")
aiv.DelShadow.shadow_path = a5.Get_Path() 'path for the shadowed DB--use in autoexec when coming back
response = ui_msg_box("Shadow Path","Shadow DB Path = "+aiv.DelShadow.shadow_path+crlf(2)+"Shadow Database Name = "+Shadow_folder_name+crlf(2)+"Are you sure you want to delete and re-create Shadow Database?",UI_QUESTION_SYMBOL+UI_YES_NO)
If response = UI_NO_SELECTED
aiv.DelShadow.Create_shadow = .F. 'set fales so when master opens nothing is triggered.
end
else
'current is a shadow, so close shadow, open Master and create a
'shadow there using the aiv.DelShadow.Create_shadow as the trigger.
aiv.DelShadow.Create_shadow = .T. 'set true so when master opens code will triger
dim Master_name as c
Master_name=a5.Get_Master_Name()
Trimmed_path = alltrim(Master_Name)
:a5.load(Trimmed_path)
end if
END
'************************ END **************
'Date Created: 18-Jan-2006 02:30:01 PM
'Last Updated: 19-Jan-2006 08:36:07 PM
'Created By : Ray Lyons
'Updated By : Ray Lyons
'*******************************Autoexec script ************************
DIM aiv AS P
DIM aiv.DelShadow AS P
aiv = addin.variables()
dim aiv.DelShadow.Create_shadow as L 'Used to trigger or not.
dim aiv.DelShadow.shadow_path as c 'Used for deleting and re-creating the shadow.
dim Master_Path as c
Master_path=a5.Get_Master_Path()'If this ="", it is NOT shadowed
If aiv.DelShadow.Create_shadow = .t. .AND. Master_path = "" 'currently in the Master, so delete & create shadow
aiv.DelShadow.Create_shadow = .F. 'so shadow won't trigger this
dim success_flag as L 'indicates whether anything was removed--not using now but may
Success_Flag = DIR_REMOVE_RECURSE(aiv.DelShadow.shadow_path,.t.) '.t. suppresses warning
DIM GLOBAL pDlg1 as {waitdialog}
pDlg1.Create(1,"Message")
pDlg1.Set_Title("Please Wait")
pDlg1.Set_Message("Operation still processing.")
pDlg1.Set_Bottom_Message("Only a few seconds left.")
dim DBname as c
DBname = file.filename_parse(a5.get_name(),"N")
xbasic_wait_for_idle(2) 'Seems to need at least a 2 sec delay or A5 really gets screwed up
pDlg1.Close()
'next line is for v6 and above. Check docs for v5 version of it
create_shadow2(aiv.DelShadow.shadow_path+"\\"+DBname,.t.)
End if
END
'*************************** END *********************************
Comment