## recallonly [ Migration: FAIL ] and recallonly [ Migration: ERROR ]

If you’re recalling data from an archive filesystem (see previous post) and you get one of these errors:

state                = recallonly [ Migration: FAIL ]

state                = recallonly [ Migration: ERROR ]

then you have at least one file that failed to recall back to the primary storage.

To view which files failed you’ll need to consult the logs which you can find at the root of the filesystem (e.g. \\mycifsshare.mydomain.com\c\$\myfilesystem). The files will be named:

migErr_vdmname_myfilesystem

migLog_vdmname_myfilesystem

and contain a list of files that failed and the log for the recall respectively.

When you have a few files listed it’s fairly easily to find the name of the file that failed in migLog by opening it in a text error and searching for the string “I/O Error”.

Chdir to /myvdm/myfilesystem/myfolder/myfolder
Migrating directory myfolder...Mon Jan 1 00:00:00 2009
creating sub-directory myfolder...Mon Jan 1 00:00:00 2009
migrating file myfilename.doc...Mon Jan 1 00:00:00 2009
migrating file myfilename.doc failed at read last byte: I/O error

The filepath in this case is \myfolder\myfolder\myfilename.doc.

The recall can fail because of an orphan stub (a stub with no data on the secondary storage). This will need a restore from your backups to get that file back. Sometimes the recall fails but the file is on the secondary storage. One way to force the recall is to copy the file and rename it, i.e.

1) Right click the stubbed file and copy

2) Past the file into the same directory to get a “copy of myfilename.doc”

3) Delete or rename the stub file

4) Rename the “Copy of myfilename.doc” back to myfilename.doc

This manual workaround works fine for when you have a small number of files but will quickly become a chore if you have tens or even thousands to perform this trick on.

So here’s couple of vbscript scripts to help parse the migLog and perform the copy and rename task.

Syntax:

cscript /nologo parse-migLog.vbs path\to\migLog > failedfiles.txt

For large log files it might help to grep out some of the content first to speed this parsing up:

grep -i -E "I\/O error|ChDir" > migLog-grepped.txt

which will trim out all the files copied successfully leaving just the directories and the failed copy lines.

The script itself:

Set objFSO = CreateObject("Scripting.FileSystemObject")

strSourceFile=WScript.Arguments.Item(0)
set objFileStream = objFSO.OpenTextFile (strSourceFile, 1)

strCurrPath=""

do until objFileStream.AtEndOfStream
if string_compare("Chdir",strLine) then strCurrPath=get_PathFromChdirLine(strLine)
if string_compare("I/O error",strLine) then
strFilePath=ltrim(rtrim(replaceFSwithBS(strCurrPath & "\" & get_FileNameFromMigratingLine(strLine))))
wscript.echo strFilePath
end if
loop

'Chdir
function get_PathFromChdirLine(strtmpLine)
strReturn=""
strReturn=Mid(strtmpLine,10,len(strtmpLine))
get_PathFromChdirLine=strReturn
end function

function get_FileNameFromMigratingLine(strtmpLine)
strReturn=""
intStringLength=len(strtmpLine)
strReturn=Mid(strtmpLine,16,intStringLength)
strReturn=left(strReturn,InStrRev(strReturn," failed"))
get_FileNameFromMigratingLine=strReturn
end function

function replaceFSwithBS(strtmp)
strReturn=strtmp
strReturn=replace(strtmp,"/","\")
replaceFSwithBS=strReturn
end function

'Compare a target string to a regular expression
private function string_compare(expression,targetstring)
set oreg= new regexp
oReg.pattern=expression
oReg.IgnoreCase = TRUE
if ("" = expression OR "" = targetstring) then
boolSearchResult=0
end if
if oReg.test (targetstring) then
boolSearchResult=1
else
boolSearchResult=0
end if
string_compare=boolSearchResult
end function

This second script performs the copy and rename using the file list generated by the previous script:

Syntax:

cscript /nologo fix-failedfiles.vbs failedfiles.txt

The script:

Set objFSO = CreateObject("Scripting.FileSystemObject")

strSourceFile=WScript.Arguments.Item(0)
set objFileStream = objFSO.OpenTextFile (strSourceFile, 1)

do until objFileStream.AtEndOfStream
on error resume next
'Copy file to new to force inflate
objFSO.CopyFile strFileName,strFileName & ".new"
if err.number > 0 then
wscript.echo strFileName
else
'rename current to .old
objFSO.MoveFile strFileName,strFileName & ".old"
'Rename copy back to original file
objFSO.MoveFile strFileName & ".new",strFileName
'delete .old
objFSO.DeleteFile strFileName & ".old"
end if
err.clear
loop

If any of the files fail to copy then they will be output to the screen.