Example #1
0
///////////////////////////////////////////////////////////////////////////////
// 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;
	}
}
Example #2
0
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;	
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}