ES1_IndexUtils.psm1
<# .NOTES =========================================================================== Copyright � 2018 Dell Inc. or its subsidiaries. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 =========================================================================== THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. IF THIS CODE AND INFORMATION IS MODIFIED, THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE AND INFORMATION REMAINS WITH THE USER. .DESCRIPTION Functions and objects for managing Indexes in a folder #> <# .SYNOPSIS Issue a "Rebuild" request for the Indexes specified .DESCRIPTION Issue a "Rebuild" request for the Indexes specified The process of rebuilding an index is handled by index servers on a scheduled basis. The completion of the rebuild operation could take some time. .PARAMETER ArchiveName The name of the archive connection .PARAMETER ArchiveFolder The archive folder containig the indexes. .PARAMETER YearMonth The year and month folder which the indexes are part of .PARAMETER IndexNumList A integer array of the index numbers to be rebuilt. .OUTPUTS List of Indexes submitted for rebuild .EXAMPLE #> function Rebuild-ES1Index{ [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact=�High�)] PARAM ( [Parameter(Mandatory=$true)] [Alias('archive')] [string] $ArchiveName, [Parameter(Mandatory=$true)] [Alias('arfolder')] [string] $ArchiveFolder, [Parameter(Mandatory=$true)] [Alias('month')] [string] $YearMonth, [Parameter(Mandatory=$true)] [Alias('idxnums')] [int []] $IndexNumList ) BEGIN { $MyDebug = $false # Do both these checks to take advantage of internal parsing of syntaxes like -Debug:$false if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("Debug") -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) { $DebugPreference = "Continue" Write-Debug "Debug Output activated" # for convenience $MyDebug = $true } try { [bool] $loaded = Add-ES1Types #-ErrorAction SilentlyContinue if (-not $loaded ) { Write-Error 'Error loading SourceOne Objects and Types' break } } catch { Write-Error $_ break } } PROCESS { try { $asmgr = new-object -ComObject ExAsAdminAPI.CoExASAdminAPI $asmgr.SetTraceInfo($Global:S1LogFile) $asmgr.Initialize() $RetIndexList=@() # Get the index flag enumeration strings/names $idxFlags=[enum]::GetNames([EMC.Interop.ExAsBaseAPI.exASIndexFlags]) # Get the specific repo. $repo = $asmgr.GetRepository($ArchiveName) $repo.SetTraceInfo($Global:S1LogFile) # Need the folderplan object to issue the "Rebuild" on $folderplan=$repo.GetFolderPlan() # Get the archive folder we need $folder = Get-Es1ArchiveFolder -ArchiveName $ArchiveName -FolderName $ArchiveFolder if ($folder -ne $null) { $folder.SetTraceInfo($Global:S1LogFile) $containerfolders=$folder.EnumerateContainerFolders() # dummy filter object because need to pass something to EnumerateIndexes but its not actually used (I looked at the underlying code) $idxFilter = $repo.CreateNewObject([EMC.Interop.ExAsAdminAPI.exASObjectType]::exASObjectType_ArchiveFolder) [bool] $FoundYM = $false foreach ($cf in $containerfolders) { if ($cf.Name -eq $YearMonth) { $FoundYM = $true $cf.SetTraceInfo($Global:S1LogFile) Write-Verbose "Year Month name: $($cf.Name)" $indexes=$cf.EnumerateIndexes($idxFilter) foreach ($index in $indexes) { Foreach($inum in $IndexNumList) { if ([int] $inum -eq [int] $index.IndexNum) { # Make sure its not alreading ReIndexing or Refreshing if ( (-not ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexFlagRefreshing)) -and ` (-not ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexFlagReindexing)) ) { if ($pscmdlet.ShouldProcess("Folder: $($cf.Name) Index: $($index.IndexNum) ?")) { # issue rebuild Write-Verbose "Issueing rebuild for $($cf.Name), $($index.IndexNum)" $folderplan.ReIndex($index.FolderID, $index.IndexNum) $RetIndexList += $index } } } } } # stop cause we processed what was specified. break } } if ( -not $FoundYM ) { throw "Error: No matching Year or month folder found for $($YearMonth)" } } else { throw "Error: Archive $($ArchiveName) or Folder $($ArchiveFolder) not found" } } catch { Write-Error $_ } finally { # These might not be 100% necessary.. [System.Runtime.Interopservices.Marshal]::ReleaseComObject($folderplan) > $null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($repo) > $null } $RetIndexList } END {} } <# .SYNOPSIS Get a list of indexes in the state(s) requested .DESCRIPTION Get a list of indexes in the state(s) requested .PARAMETER ArchiveName The name of the archive connection .PARAMETER ArchiveFolder The archive folder containig the indexes. .PARAMETER YearMonth The year and month folder which the indexes are part of. Can only be used in conjuction with the ArchiveFolder parameter .PARAMETER States List of states. The States correlate to some common combinations of the [EMC.Interop.ExAsBaseAPI.exASIndexFlags] enum of the volume flag bits. REPAIRING will return Indexes with ReIndexing or Refreshing bits sets CORRUPT will return Indexes with the Corrupt bit set INCOMPLETE will return Indexes with the any of the InconsistentAncillaryDB,MissingMsgs, Missing, MissingACE, MissingBCC, MissingOwner, or MissingRecpts bit set UNPERFORMEDTRANS will return Indexes with the UnperformedTrans bit set .OUTPUTS List of Indexes in the requested state(s) .EXAMPLE #> Function Get-ES1IndexByState { [CmdletBinding()] PARAM( [Parameter(Mandatory=$true)] [Alias('archive')] [string] $ArchiveName, [Parameter(Mandatory=$false)] [Alias('name')] [string] $ArchiveFolder, [Parameter(Mandatory=$false)] [Alias('month')] [string] $YearMonth, [Parameter(Mandatory=$true)] [ValidateSet ("REPAIRING","CORRUPT","INCOMPLETE","UNPERFORMEDTRANS")] [string[]] $States ) BEGIN{ $MyDebug = $false # The YearMonth parameter only make sense when an ArchiveFolder is specified. Otherwise you might get some meaningless results if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("YearMonth") -and(-not $PSCmdlet.MyInvocation.BoundParameters.ContainsKey("ArchiveFolder"))) { Write-Error "Argument Error: YearMonth can only be specified with an ArchiveFolder" break } # Do both these checks to take advantage of internal parsing of syntaxes like -Debug:$false if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("Debug") -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) { $DebugPreference = "Continue" Write-Debug "Debug Output activated" # for convenience $MyDebug = $true } try { [bool] $loaded = Add-ES1Types #-ErrorAction SilentlyContinue if (-not $loaded ) { Write-Error 'Error loading SourceOne Objects and Types' break } } catch { Write-Error $_ break } } PROCESS{ try { $asmgr = new-object -ComObject ExAsAdminAPI.CoExASAdminAPI $asmgr.SetTraceInfo($Global:S1LogFile) $asmgr.Initialize() $RetIndexList=@() # Get the index flag enumeration strings/names $idxFlags=[enum]::GetNames([EMC.Interop.ExAsBaseAPI.exASIndexFlags]) # Get the specific repo. $repo = $asmgr.GetRepository($ArchiveName) $repo.SetTraceInfo($Global:S1LogFile) $folderplan=$repo.GetFolderPlan() $folders = @($folderplan.EnumerateArchiveFolders()) # If an archive folder was specified only process that one... if ($ArchiveFolder ) { foreach ($folder in $folders) { if (($folder.Name -eq $ArchiveFolder) ) { $folders = @($folder) break; } } } # dummy object because need to pass something but its not actually used $idxFilter = $repo.CreateNewObject([EMC.Interop.ExAsAdminAPI.exASObjectType]::exASObjectType_ArchiveFolder) foreach ($folder in $folders) { $containerfolders=$folder.EnumerateContainerFolders() foreach ($cf in $containerfolders) { # # Process only the YMFolder if specified. # if ($YearMonth -and ($YearMonth -ne $cf.Name) ) { continue } $cf.SetTraceInfo($Global:S1LogFile) $indexes=$cf.EnumerateIndexes($idxFilter) Write-Verbose "Archive Folder: $($ArchiveFolder) YearMonth : $($cf.Name) Index Count $($indexes.Count)" foreach ($index in $indexes) { $roles = @() for ($i = 0 ; $i -lt ($idxFlags.Length); $i++) { [int] $bits = [EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i] # there are some inconsistent names in the EMC.Interop.ExAsBaseAPI.exASIndexFlags so making the string # readable friendly takes a little extra work if ($index.IndexState -band $bits) { if (([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Contains('exASIndexMissing') -or ` ([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Contains('exASIndex4xMBCSIndex') -or ` ([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Contains('exASIndexESIndex') ) { $roles += ([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Substring(9) } elseif (([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Contains('exAsInconsistent')) { $roles += ([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Substring(4) } else { $roles += ([EMC.Interop.ExAsBaseAPI.exASIndexFlags]$idxFlags[$i]).ToString().Substring(13) } } } # add a user readable string representation of the flags $index | Add-Member NoteProperty -Name "ArchiveFolder" -Value $folder.Name $index | Add-Member NoteProperty -Name "FolderName" -Value $cf.Name $index | Add-Member NoteProperty -Name "IndexStatus" -Value $roles foreach ($state in $States) { if ( ($state -eq 'REPAIRING') -and ` (($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexFlagRefreshing) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexFlagReindexing) )) { $RetIndexList += $index break } if ( ($state -eq 'CORRUPT') -and ` (($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexFlagCorrupt) )) { $RetIndexList += $index break } if ( ($state -eq 'UNPERFORMEDTRANS') -and ` (($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexFlagUnperformedTrans) )) { $RetIndexList += $index break } if ( ($state -eq 'INCOMPLETE') -and ` (($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exAsInconsistentAncillaryDB) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissingMsgs) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissing) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissingBusinessFolder) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissingACE) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissingBCC) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissingOwner) -or ` ($index.IndexState -band [EMC.Interop.ExAsBaseAPI.exASIndexFlags]::exASIndexMissingRecpts) ) ) { $RetIndexList += $index break } } } } } } catch { Write-Error $_ } finally { # These might not be 100% necessary.. [System.Runtime.Interopservices.Marshal]::ReleaseComObject($folderplan) > $null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($repo) > $null } $RetIndexList } END{} } Export-ModuleMember -Function * -Alias * |