/////////////////////////////////////////////////////////////////////////////// // CMirDiskUIHandler /////////////////////////////////////////////////////////////////////////////// UINT CMirDiskUIHandler::GetIconID(CDiskObjectPtr obj) const { ATLASSERT( dynamic_cast<const CMirDiskObject*>(obj.get()) != NULL ); CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(obj); if ( mirDisk->IsBroken() ) { return IDI_NDMIRR_BROKEN; } else { return IDI_NDMIRR_OK; } }
PropertyList CMirDiskUIHandler::GetPropertyList(CDiskObjectPtr obj) const { PropertyList propList; PropertyListItem propItem; WTL::CString strBuffer; CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(obj); propItem.strName.LoadString( IDS_UIHANDLER_PROPERTY_DIRTY ); if ( mirDisk->IsDirty() ) propItem.strValue.LoadString( IDS_UIHANDLER_PROPERTY_DIRTY_TRUE ); else propItem.strValue.LoadString( IDS_UIHANDLER_PROPERTY_DIRTY_FALSE ); propItem.strToolTip.LoadString( IDS_UIHANDLER_PROPERTY_DIRTY_TOOLTIP ); propList.push_back( propItem ); return propList; }
UINT32 CDiskObjectComposite::GetNDASMediaType() const { UINT32 iMediaType = NMT_INVALID; // return the first NDAS Media type of unit disk which is not NMT_INVALID const_iterator itr; for ( itr = begin(); itr != end(); ++itr ) { if(::IsEmptyDisk(*itr)) continue; if(!(*itr)->IsUnitDisk()) { CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(*itr); if(mirDisk) { iMediaType = mirDisk->GetNDASMediaType(); if(NMT_INVALID != iMediaType) return iMediaType; } else { return NMT_INVALID; } } if(0 == (*itr)->GetDiskCount()) // skip empty one continue; CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*itr); CUnitDiskInfoHandlerPtr unitHandler = unitDisk->GetInfoHandler(); iMediaType = unitHandler->GetNDASMediaType(); if(NMT_INVALID != iMediaType) return iMediaType; } return iMediaType; }
void CMirrorDlg::SetSyncDisks(CMirDiskObjectPtr mirDisks) { // TODO : How do we select source disk? UINT nDirtyCount = mirDisks->GetDirtyDiskCount(); ATLASSERT ( nDirtyCount > 0 ); if ( nDirtyCount > 1 ) { // TODO : Not implemented(We need to ask user to select one) } UINT nDirtyDiskIdx = mirDisks->GetDirtyDiskIndex(); if ( nDirtyDiskIdx == 0 ) { m_pSource = boost::dynamic_pointer_cast<CUnitDiskObject>(mirDisks->front()); m_pDest = boost::dynamic_pointer_cast<CUnitDiskObject>(mirDisks->back()); } else { m_pSource = boost::dynamic_pointer_cast<CUnitDiskObject>(mirDisks->back()); m_pDest = boost::dynamic_pointer_cast<CUnitDiskObject>(mirDisks->front()); } m_pMirDisks = mirDisks; }
BOOL CDiskObjectComposite::HasWriteAccess() { UINT32 iMediaType = NMT_INVALID; // return the first NDAS Media type of unit disk which is not NMT_INVALID const_iterator itr; for ( itr = begin(); itr != end(); ++itr ) { if(::IsEmptyDisk(*itr)) return FALSE; if(!(*itr)->IsUnitDisk()) { CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(*itr); if(mirDisk) { if(!mirDisk->HasWriteAccess()) return FALSE; } else { return FALSE; } } // if(2 != (*itr)->GetDiskCount()) // return FALSE; CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*itr); if(!(unitDisk->GetAccessMask() & GENERIC_WRITE)) return FALSE; } return TRUE; }
CCommandSet CMirDiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const { ATLASSERT( dynamic_cast<const CMirDiskObject*>(obj.get()) != NULL ); CCommandSet setCommand; BOOL bCanWrite; CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(obj); bCanWrite = mirDisk->GetAccessMask() & GENERIC_WRITE; setCommand.push_back( CCommand( IDM_TOOL_UNBIND, bCanWrite ) ); if(NMT_MIRROR == mirDisk->GetNDASMediaType()) { // migrate : mirror -> RAID 1 setCommand.push_back( CCommand( IDM_TOOL_MIGRATE, !mirDisk->IsBroken() && mirDisk->HasWriteAccess())); } else { // do not check IsDirty here (cause it takes some time) setCommand.push_back( CCommand( IDM_TOOL_SYNCHRONIZE, /* bCanWrite && */ mirDisk->IsDirty() && !mirDisk->IsBroken() && mirDisk->HasWriteAccess())); } return setCommand; }
BOOL CMirDiskUIHandler::OnSynchronize(CDiskObjectPtr obj) const { ATLASSERT( dynamic_cast<CMirDiskObject*>(obj.get()) != NULL ); CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(obj); CUnitDiskObjectPtr sourceDisk, destDisk; BOOL bFirstDefected, bSecondDefected; BOOL bResults; bResults = mirDisk->GetDirtyDiskStatus(&bFirstDefected, &bSecondDefected); if(!bResults) return FALSE; // check dirty status here // ATLASSERT( mirDisk->GetDirtyDiskCount() > 0 ); if ( !bFirstDefected && !bSecondDefected) { WTL::CString strMsg; strMsg.LoadString(IDS_WARNING_NOT_NEED_RECOVER ); WTL::CString strTitle; strTitle.LoadString(IDS_APPLICATION); MessageBox( ::GetFocus(), strMsg, strTitle, MB_OK | MB_ICONERROR ); return TRUE; } // // Select the source disk and the dest disk // if ( bFirstDefected && bSecondDefected) { CSelectDiskDlg dlgSelect(IDD_SELSOURCE); CDiskObjectList listDisks; listDisks.push_back( mirDisk->front() ); listDisks.push_back( mirDisk->back() ); dlgSelect.SetSingleDisks( listDisks ); if ( dlgSelect.DoModal() != IDOK ) return TRUE; sourceDisk = dlgSelect.GetSelectedDisk(); if ( sourceDisk == mirDisk->front() ) destDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(mirDisk->back()); else destDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(mirDisk->front()); } else { if (bFirstDefected) { sourceDisk = /*boost::dynamic_pointer_cast<CUnitDiskObject>*/ (mirDisk->SecondDisk()); destDisk = /*boost::dynamic_pointer_cast<CUnitDiskObject>*/ (mirDisk->FirstDisk()); } else if (bSecondDefected ) { sourceDisk = /*boost::dynamic_pointer_cast<CUnitDiskObject>*/ (mirDisk->FirstDisk()); destDisk = /*boost::dynamic_pointer_cast<CUnitDiskObject>*/ (mirDisk->SecondDisk()); } else { return FALSE; } } // // Synchronize // CRecoverDlg dlgRecover(FALSE, IDS_LOGDEV_TYPE_DISK_RAID1, IDS_RECOVERDLG_TASK_RECOVER); dlgRecover.SetMemberDevice(destDisk); dlgRecover.DoModal(); CNdasHIXChangeNotify HixChangeNotify(pGetNdasHostGuid()); bResults = HixChangeNotify.Initialize(); if(bResults) { NDAS_UNITDEVICE_ID unitDeviceId; CopyMemory(unitDeviceId.DeviceId.Node, sourceDisk->GetLocation()->GetUnitDiskLocation()->MACAddr, sizeof(unitDeviceId.DeviceId.Node)); unitDeviceId.UnitNo = sourceDisk->GetLocation()->GetUnitDiskLocation()->UnitNumber; HixChangeNotify.Notify(unitDeviceId); CopyMemory(unitDeviceId.DeviceId.Node, destDisk->GetLocation()->GetUnitDiskLocation()->MACAddr, sizeof(unitDeviceId.DeviceId.Node)); unitDeviceId.UnitNo = destDisk->GetLocation()->GetUnitDiskLocation()->UnitNumber; HixChangeNotify.Notify(unitDeviceId); } return TRUE; }
BOOL CMirDiskUIHandler::OnMigrate(CDiskObjectPtr obj ) const { CMirDiskObjectPtr mirDisk = boost::dynamic_pointer_cast<CMirDiskObject>(obj); if(NMT_MIRROR != mirDisk->GetNDASMediaType()) return FALSE; UINT32 BindResult; CDiskObjectPtr disk = obj; NDASCOMM_CONNECTION_INFO pConnectionInfo[NUMBER_MIGRATE_DISK]; UINT32 i; WTL::CString strTitle; strTitle.LoadString(IDS_APPLICATION); // Find aggregation root if (NUMBER_MIGRATE_DISK != disk->GetDiskCount()) { WTL::CString strMsg; strMsg.LoadString( IDS_DISKPROPERTYPAGE_MIGRATE_DISK_NOT_EXIST ); MessageBox( ::GetFocus(), strMsg, strTitle, MB_OK | MB_ICONWARNING ); return FALSE; } WTL::CString strConfirmMsg; strConfirmMsg.LoadString( IDS_DISKPROPERTYPAGE_MIGRATE_CONFIRM ); if ( IDYES != MessageBox( ::GetFocus(), strConfirmMsg, strTitle, MB_YESNO | MB_ICONWARNING ) ) { return FALSE; } if ( !disk->CanAccessExclusive() ) { WTL::CString strMsg; strMsg.LoadString( IDS_FAIL_TO_ACCESS_EXCLUSIVELY ); MessageBox( ::GetFocus(), strMsg, strTitle, MB_OK | MB_ICONWARNING ); return FALSE; } CDiskObjectCompositePtr pDiskObjectComposite = boost::dynamic_pointer_cast<CDiskObjectComposite>(disk); CDiskObjectComposite::const_iterator itr; for (itr = pDiskObjectComposite->begin(), i = 0; itr != pDiskObjectComposite->end(); ++itr, ++i) { CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*itr); ZeroMemory(&pConnectionInfo[i], sizeof(NDASCOMM_CONNECTION_INFO)); pConnectionInfo[i].address_type = NDASCOMM_CONNECTION_INFO_TYPE_ADDR_LPX; pConnectionInfo[i].login_type = NDASCOMM_LOGIN_TYPE_NORMAL; pConnectionInfo[i].UnitNo = unitDisk->GetLocation()->GetUnitDiskLocation()->UnitNumber; pConnectionInfo[i].bWriteAccess = TRUE; pConnectionInfo[i].ui64OEMCode = NULL; pConnectionInfo[i].bSupervisor = FALSE; pConnectionInfo[i].protocol = NDASCOMM_TRANSPORT_LPX; CopyMemory(pConnectionInfo[i].AddressLPX, unitDisk->GetLocation()->GetUnitDiskLocation()->MACAddr, LPXADDR_NODE_LENGTH); } BindResult = NdasOpBind(NUMBER_MIGRATE_DISK, pConnectionInfo, NMT_RAID1); WTL :: CString strMsg; if(NUMBER_MIGRATE_DISK == BindResult) { strMsg.LoadString(IDS_DISKPROPERTYPAGE_MIGRATE_SUCCESS); WTL::CString strTitle; strTitle.LoadString(IDS_APPLICATION); MessageBox( ::GetFocus(), strMsg, strTitle, MB_OK|MB_ICONINFORMATION ); } else { DWORD dwLastError = ::GetLastError(); switch(dwLastError) { case NDASCOMM_ERROR_RW_USER_EXIST: case NDASOP_ERROR_ALREADY_USED: case NDASOP_ERROR_DEVICE_FAIL: case NDASOP_ERROR_NOT_SINGLE_DISK: case NDASOP_ERROR_DEVICE_UNSUPPORTED: case NDASOP_ERROR_NOT_BOUND_DISK: // does not return this error for (itr = pDiskObjectComposite->begin(), i = 0; itr != pDiskObjectComposite->end(); ++itr, ++i) { CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*itr); if(BindResult == i) strMsg.FormatMessage(IDS_DISKPROPERTYPAGE_MIGRATE_FAIL_AT_FMT, unitDisk->GetTitle()); } break; default: strMsg.LoadString(IDS_DISKPROPERTYPAGE_MIGRATE_FAIL); break; } ShowErrorMessageBox(strMsg); } CNdasHIXChangeNotify HixChangeNotify(pGetNdasHostGuid()); BOOL bResults = HixChangeNotify.Initialize(); if(bResults) { for(i = 0; i < NUMBER_MIGRATE_DISK; i++) { NDAS_UNITDEVICE_ID unitDeviceId; CopyMemory(unitDeviceId.DeviceId.Node, pConnectionInfo[i].AddressLPX, sizeof(unitDeviceId.DeviceId.Node)); unitDeviceId.UnitNo = pConnectionInfo[i].UnitNo; HixChangeNotify.Notify(unitDeviceId); } } return TRUE; }
WTL::CString CObjectUIHandler::GetFaultTolerance(CDiskObjectPtr obj) const { WTL::CString strTitle; strTitle = _T(""); if(obj->IsUnitDisk()) { if((dynamic_cast<CEmptyDiskObject*>(obj.get()) == NULL)) { CDiskObjectPtr parent; CUnitDiskObjectPtr pUnitDiskObject = boost::dynamic_pointer_cast<CUnitDiskObject>(obj); if(!(parent = pUnitDiskObject->GetParent())->IsRoot()) { CDiskObjectCompositePtr pDiskObjectComposite = boost::dynamic_pointer_cast<CDiskObjectComposite>(parent); if (NMT_RAID4 == pDiskObjectComposite->GetNDASMediaType()) { UINT8 child_status = pDiskObjectComposite->RMDUnitStatus(pUnitDiskObject->GetLocation()->GetUnitDiskLocation()); if(NDAS_UNIT_META_BIND_STATUS_FAULT & child_status) { strTitle.LoadString(IDS_FT_FAULT_CHILD); } else if(NDAS_UNIT_META_BIND_STATUS_SPARE & child_status) { strTitle.LoadString(IDS_FT_FAULT_SPARE); } } } else { strTitle.LoadString(IDS_FT_UNIT); } } } else { CDiskObjectCompositePtr pDiskObjectComposite = boost::dynamic_pointer_cast<CDiskObjectComposite>(obj); // check missing member if(pDiskObjectComposite->IsBroken()) { strTitle.LoadString(IDS_FT_MISSING); } else { switch(pDiskObjectComposite->GetNDASMediaType()) { case NMT_AGGREGATE: case NMT_RAID0: case NMT_MIRROR: if(pDiskObjectComposite->IsBroken()) strTitle.LoadString(IDS_FT_MISSING); else strTitle.LoadString(IDS_FT_NOT_FAULT_TOLERANT); break; case NMT_RAID1: { CMirDiskObjectPtr pMirDiskObject = boost::dynamic_pointer_cast<CMirDiskObject>(pDiskObjectComposite); if(pMirDiskObject->IsBroken()) strTitle.LoadString(IDS_FT_NEED_REPAIR); else if(pMirDiskObject->IsDirty()) strTitle.LoadString(IDS_FT_DIRTY); else strTitle.LoadString(IDS_FT_FAULT_TOLERANT); } break; case NMT_RAID4: { CRAID4DiskObjectPtr pRAID4DiskObject = boost::dynamic_pointer_cast<CRAID4DiskObject>(pDiskObjectComposite); if(pRAID4DiskObject->IsBroken()) { strTitle.LoadString(IDS_FT_NEED_REPAIR); } else { switch(pDiskObjectComposite->RMDStatus()) { case 0: strTitle.LoadString(IDS_FT_FAULT_TOLERANT); break; case 1: strTitle.LoadString(IDS_FT_DIRTY); break; case 2: strTitle.LoadString(IDS_FT_FAULT); break; case 3: strTitle.LoadString(IDS_FT_IN_SYNC); break; default: break; } } } break; default: break; } } } return strTitle; }
CCommandSet CUnitDiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const { ATLASSERT( dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL); CCommandSet setCommand; CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(obj); CUnitDiskInfoHandlerPtr handler = unitDisk->GetInfoHandler(); BOOL bCanWrite; if ( handler->IsBound() ) { CDiskObjectPtr aggrRoot = unitDisk->GetParent(); if ( aggrRoot->IsRoot() ) { // This can occur when the tree is updated just after // the disk is bound. // This additional if code prevents error. setCommand.push_back( CCommand(IDM_TOOL_UNBIND) ); } else { while ( !aggrRoot->GetParent()->IsRoot() ) aggrRoot = aggrRoot->GetParent(); // To Unbind, we should have write privilege to all the disks in bind setCommand.push_back( CCommand(IDM_TOOL_UNBIND, aggrRoot->GetAccessMask() & GENERIC_WRITE) ); } } else { bCanWrite = unitDisk->GetAccessMask() & GENERIC_WRITE; setCommand.push_back( CCommand(IDM_TOOL_ADDMIRROR, bCanWrite) ); } if ( handler->IsMirrored() ) { CMirDiskObjectPtr parent = boost::dynamic_pointer_cast<CMirDiskObject>(unitDisk->GetParent()); if ( parent.get() != NULL ) { // To synchronize, we have write privilege to the two disks in mirroring setCommand.push_back( CCommand(IDM_TOOL_SYNCHRONIZE, (parent->GetAccessMask() & GENERIC_WRITE) && parent->IsDirty() && !parent->IsBroken() && parent->HasWriteAccess() ) ); } CDiskObjectPtr aggrRoot = unitDisk->GetParent(); if ( aggrRoot->IsRoot() ) { // This can occur when the tree is updated just after // the disk is bound. // This additional if code prevents error. setCommand.push_back( CCommand(IDM_TOOL_UNBIND) ); } else { while ( !aggrRoot->GetParent()->IsRoot() ) aggrRoot = aggrRoot->GetParent(); } } else if(NMT_RAID4 == handler->GetNDASMediaType()) { CRAID4DiskObjectPtr parent = boost::dynamic_pointer_cast<CRAID4DiskObject>(unitDisk->GetParent()); if ( parent.get() != NULL ) { // To synchronize, we have write privilege to the two disks in mirroring setCommand.push_back( CCommand(IDM_TOOL_SYNCHRONIZE, (parent->GetAccessMask() & GENERIC_WRITE) && parent->IsDirty() && !parent->IsBroken() ) ); } } if(unitDisk->IsUnitDisk()) { setCommand.push_back( CCommand(IDM_TOOL_SINGLE) ); } return setCommand; }
CDiskObjectPtr CDiskObjectBuilder::Build(const CDeviceInfoList listDevice, LPREFRESH_STATUS pFuncRefreshStatus, void *context) { CUnitDiskObjectList listDiskObj; CDiskObjectCompositePtr root; CUnitDiskObjectList::const_iterator found; // // Build list of unit disks from the device list // listDiskObj = BuildDiskObjectList(listDevice, pFuncRefreshStatus, context); // // Construct structure of disks including aggregation and mirroring // root = CDiskObjectCompositePtr(new CRootDiskObject()); while ( !listDiskObj.empty() ) { CUnitDiskObjectPtr disk; disk = listDiskObj.front(); CUnitDiskInfoHandlerPtr pInfoHandler = disk->GetInfoHandler(); if ( !pInfoHandler->IsHDD() ) { listDiskObj.pop_front(); continue; // Only HDD type disk is supported.(This may be changed later) } if ( pInfoHandler->IsBound() ) { CDiskLocationVector vtLocation = pInfoHandler->GetBoundDiskLocations(disk->GetLocation()); if(NMT_RAID4 == pInfoHandler->GetNDASMediaType()) { CDiskObjectCompositePtr raid4Disks = CDiskObjectCompositePtr(new CRAID4DiskObject()); for(UINT i = 0; i < vtLocation.size(); i++) { found = std::find_if( listDiskObj.begin(), listDiskObj.end(), std::bind1st(CDiskLocationEqual(), vtLocation[i])); if(found != listDiskObj.end() && ::HasSameBoundDiskList(*found, disk)) { raid4Disks->AddChild(raid4Disks, *found); listDiskObj.erase(found); } else { raid4Disks->AddChild(raid4Disks, ::CreateEmptyDiskObject()); } } root->AddChild(root, raid4Disks); } else if ( pInfoHandler->IsBoundAndNotSingleMirrored() ) { CDiskObjectCompositePtr aggrDisks = CDiskObjectCompositePtr(new CAggrDiskObject()); if ( pInfoHandler->IsMirrored() ) // double tree { for ( UINT i=0; i < vtLocation.size(); i+= 2 ) { CMirDiskObjectPtr mirDisks = CMirDiskObjectPtr( new CMirDiskObject() ); int emptydisk = 0; // find first of the pair found = std::find_if( listDiskObj.begin(), listDiskObj.end(), std::bind1st(CDiskLocationEqual(), vtLocation[i]) ); if ( found != listDiskObj.end() && ::HasSameBoundDiskList(*found, disk) ) { mirDisks->AddChild( mirDisks, *found ); listDiskObj.erase(found); } else { // create empty unit disk emptydisk++; } // find second of the pair found = std::find_if( listDiskObj.begin(), listDiskObj.end(), std::bind1st(CDiskLocationEqual(), vtLocation[i+1]) ); if ( found != listDiskObj.end() && ::HasSameBoundDiskList(*found, disk) ) { mirDisks->AddChild( mirDisks, *found ); listDiskObj.erase(found); } else { // create empty unit disk emptydisk++; } if(0 == emptydisk) { } else if(1 == emptydisk) { mirDisks->AddChild( mirDisks, ::CreateEmptyDiskObject()); } else { listDiskObj.pop_front(); root->AddChild( root, disk ); break; } if ( mirDisks->size() != 0 ) // always 2 including empty disks aggrDisks->AddChild( aggrDisks, mirDisks ); } } else { BOOL bFound = FALSE, bFoundSelf = FALSE; for ( UINT i=0; i < vtLocation.size(); i++ ) { CDiskLocationPtr p = vtLocation[i]; found = std::find_if( listDiskObj.begin(), listDiskObj.end(), std::bind1st(CDiskLocationEqual(), vtLocation[i]) ); if ( found != listDiskObj.end() && ::HasSameBoundDiskList(*found, disk) ) { bFound = TRUE; if(*found == disk) bFoundSelf = TRUE; aggrDisks->AddChild( aggrDisks, *found ); listDiskObj.erase(found); } else { // create empty unit disk aggrDisks->AddChild( aggrDisks, ::CreateEmptyDiskObject()); } } if(!bFound) { listDiskObj.pop_front(); root->AddChild( root, disk ); break; } if(!bFoundSelf) { listDiskObj.pop_front(); root->AddChild( root, disk ); } } root->AddChild( root, aggrDisks ); } else if ( pInfoHandler->IsMirrored() ) { CMirDiskObjectPtr mirDisks = CMirDiskObjectPtr( new CMirDiskObject() ); UINT i = 0; int emptydisk = 0; // find first of the pair found = std::find_if( listDiskObj.begin(), listDiskObj.end(), std::bind1st(CDiskLocationEqual(), vtLocation[i]) ); if ( found != listDiskObj.end() && ::HasSameBoundDiskList(*found, disk) ) { mirDisks->AddChild( mirDisks, *found ); listDiskObj.erase(found); } else { // create empty unit disk emptydisk++; } // find second of the pair found = std::find_if( listDiskObj.begin(), listDiskObj.end(), std::bind1st(CDiskLocationEqual(), vtLocation[i+1]) ); if ( found != listDiskObj.end() && ::HasSameBoundDiskList(*found, disk) ) { mirDisks->AddChild( mirDisks, *found ); listDiskObj.erase(found); } else { // create empty unit disk emptydisk++; } if(0 == emptydisk) { } else if(1 == emptydisk) { mirDisks->AddChild( mirDisks, ::CreateEmptyDiskObject()); } else { listDiskObj.pop_front(); root->AddChild( root, disk ); break; } root->AddChild(root, mirDisks); } else { listDiskObj.pop_front(); root->AddChild( root, disk ); } } else // pDiskInfoHander->IsBound() { listDiskObj.pop_front(); root->AddChild( root, disk ); } } // while ( !listDiskObj.empty() ) return root; }