UINT32 CMirDiskObject::GetNDASMediaType() const { if(::IsEmptyDisk(FirstDisk())) { if(::IsEmptyDisk(SecondDisk())) return NMT_INVALID; else { CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(SecondDisk()); CUnitDiskInfoHandlerPtr unitHandler = unitDisk->GetInfoHandler(); return unitHandler->GetNDASMediaType(); } } else { CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(FirstDisk()); CUnitDiskInfoHandlerPtr unitHandler = unitDisk->GetInfoHandler(); return unitHandler->GetNDASMediaType(); } }
BOOL HasSameBoundDiskList(CUnitDiskObjectPtr first, CUnitDiskObjectPtr second) { CDiskLocationVector vtFirst, vtSecond; CUnitDiskInfoHandlerPtr handlerFirst, handlerSecond; handlerFirst = first->GetInfoHandler(); handlerSecond = second->GetInfoHandler(); if ( !handlerFirst->IsBound() || !handlerSecond->IsBound() ) { return FALSE; } vtFirst = handlerFirst->GetBoundDiskLocations( first->GetLocation() ); vtSecond = handlerSecond->GetBoundDiskLocations( second->GetLocation() ); if ( vtFirst.size() != vtSecond.size() ) return FALSE; for ( UINT i=0; i < vtFirst.size(); i++ ) { if ( !vtFirst[i]->Equal(vtSecond[i]) ) return FALSE; } return TRUE; }
/////////////////////////////////////////////////////////////////////////////// // CUnitDiskUIHandler /////////////////////////////////////////////////////////////////////////////// UINT CUnitDiskUIHandler::GetIconID(CDiskObjectPtr obj) const { ATLASSERT(dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL); CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(obj); CUnitDiskInfoHandlerPtr handler = unitDisk->GetInfoHandler(); if ( !obj->IsUsable() ) return IDI_ND_BADKEY; if ( handler->IsHDD() ) { if ( handler->IsBound() ) { if ( handler->IsMaster() ) { return IDI_ND_INUSE; } else { return IDI_ND_SLAVE; } } else { return IDI_ND_INUSE; } } else { // TODO : We need a new icon for this type(DVD, FLASH, MO.. ETC) return IDI_ND_INUSE; } }
const CObjectUIHandler *CObjectUIHandler::GetUIHandler(CDiskObjectPtr obj) { // TODO : More sophisticated way of determining uihandler based on the // status of the disks is necessary. static CAggrDiskUIHandler aggrUIHandler; static CMirDiskUIHandler mirUIHandler; static CEmptyDiskUIHandler emptyUIHandler; static CRAID4DiskUIHandler raid4UIHandler; static CUnitDiskUIHandler unitDiskUIHandler; static CUnsupportedDiskUIHandler unsupportedDiskUIHandler; if ( dynamic_cast<const CAggrDiskObject*>(obj.get()) != NULL ) return &aggrUIHandler; if ( dynamic_cast<const CMirDiskObject*>(obj.get()) != NULL ) return &mirUIHandler; if ( dynamic_cast<const CRAID4DiskObject*>(obj.get()) != NULL ) return &raid4UIHandler; if ( dynamic_cast<const CEmptyDiskObject*>(obj.get()) != NULL ) return &emptyUIHandler; if ( dynamic_cast<const CUnitDiskObject*>(obj.get()) != NULL ) { CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(obj); CUnitDiskInfoHandlerPtr infoHandler = unitDisk->GetInfoHandler(); if ( infoHandler->HasValidInfo() ) return &unitDiskUIHandler; else return &unsupportedDiskUIHandler; } return &unitDiskUIHandler; }
PropertyList CUnitDiskUIHandler::GetPropertyList(CDiskObjectPtr obj) const { PropertyList propList; PropertyListItem propItem; WTL::CString strBuffer; CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(obj); CUnitDiskInfoHandlerPtr handler = unitDisk->GetInfoHandler(); CHDDDiskInfoHandler *pHDDHandler = dynamic_cast<CHDDDiskInfoHandler*>(handler.get()); if ( pHDDHandler != NULL ) { // TODO : String resources propItem.strName.LoadString( IDS_UIHANDLER_PROPERTY_MODEL ); propItem.strValue = pHDDHandler->GetModelName(); propItem.strToolTip.LoadString( IDS_UIHANDLER_PROPERTY_MODEL_TOOLTIP ); propList.push_back( propItem ); propItem.strName.LoadString( IDS_UIHANDLER_PROPERTY_SERIALNO ); propItem.strValue = pHDDHandler->GetSerialNo(); propItem.strToolTip.LoadString( IDS_UIHANDLER_PROPERTY_SERIALNO_TOOLTIP ); propList.push_back( propItem ); } return propList; }
CUnitDiskObjectPtr FindMirrorDisk(CUnitDiskObjectPtr src, CUnitDiskObjectList disks) { CUnitDiskInfoHandlerPtr handler = src->GetInfoHandler(); ATLASSERT( handler->IsMirrored() ); CUnitDiskObjectList::const_iterator found; found = std::find_if ( disks.begin(), disks.end(), std::bind1st( CDiskLocationEqual(), handler->GetPeerLocation() ) ); if ( found == disks.end() ) { return CUnitDiskObjectPtr(); } return *found; }
void CUnBindDlg::SetDiskToUnbind(CDiskObjectPtr obj) { m_pDiskUnbind = obj; CFindIfVisitor<TRUE> unitDiskFinder; CDiskObjectList listUnbind; // List of disks to unbind listUnbind = unitDiskFinder.FindIf( m_pDiskUnbind, IsUnitDisk); // // Data is deleted only when the disks are aggregated // Thus, change message if they are not. // CUnitDiskObjectPtr unitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(listUnbind.front()); if ( unitDisk->GetInfoHandler()->IsBoundAndNotSingleMirrored() ) { IDD = IDD_UNBIND_MIRROR; } }
UINT32 CRAID4DiskObject::GetNDASMediaType() const { CUnitDiskObjectPtr pUnitDisk; std::list<CDiskObjectPtr>::iterator it; for(it = begin(); it != end(); ++it) { pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it); if(!::IsEmptyDisk(pUnitDisk)) { CUnitDiskInfoHandlerPtr unitHandler = pUnitDisk->GetInfoHandler(); return unitHandler->GetNDASMediaType(); } } return NMT_INVALID; }
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; }
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; }
BOOL WINAPI NdasBindUnitDevices(PNDAS_UNITDEVICE_GROUP pUnitDeviceIdGroup, NDAS_UNITDEVICE_DISK_TYPE diskType) { int nBindType; BOOL bResult; _ASSERT(FALSE); // // Basic validation of parameters // switch( diskType ) { case NDAS_UNITDEVICE_DISK_TYPE_AGGREGATED: nBindType = NMT_AGGREGATE; break; case NDAS_UNITDEVICE_DISK_TYPE_RAID1: if ( (pUnitDeviceIdGroup->cUnitDevices % 2) != 0 ) return FALSE; // ERROR : Number of disks must be even. nBindType = NMT_RAID1; break; // TODO : diskType that has been changed by aingoppa should be applied here. default: // ERROR : Invalid parameters return FALSE; } bResult = IsValidBindDiskCount(nBindType, pUnitDeviceIdGroup->cUnitDevices); if ( !bResult ) { // ERROR : Invalid number of disks. return FALSE; } // // Create disk objects // CUnitDiskObjectVector vtUnitDisks; CUnitDiskObjectPtr unitDisk; UINT i; for ( i=0; i < pUnitDeviceIdGroup->cUnitDevices; i++ ) { unitDisk = NdasCreateUnitDiskObject( &pUnitDeviceIdGroup->aUnitDevices[i] ); if ( unitDisk.get() == NULL ) return FALSE; // // Validation of disks // if ( unitDisk->GetInfoHandler()->IsBound() ) return FALSE; // ERROR : disk is already bound. vtUnitDisks.push_back(unitDisk); } // // Bind disks // for ( i=0; i < vtUnitDisks.size(); i++ ) { if ( !vtUnitDisks[i]->CanAccessExclusive() ) { // ERROR : cannot access disk exclusively return FALSE; } } try { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Open( TRUE ); } } catch ( CNDASException & ) { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Close(); } // ERROR : Fail to connect to disk return FALSE; } for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Bind( vtUnitDisks, i, nBindType ); } try { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->CommitDiskInfo(); } } catch ( CNDASException & ) { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Close(); } // ERROR : Unexpected error while writing return FALSE; } for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Close(); } return TRUE; }
BOOL WINAPI NdasUnBindUnitDevices(PNDAS_UNITDEVICE_GROUP pUnitDeviceIdGroup) { UINT i; CUnitDiskObjectVector vtUnitDisks; CUnitDiskObjectPtr unitDisk; for ( i=0; i < pUnitDeviceIdGroup->cUnitDevices; i++ ) { unitDisk = NdasCreateUnitDiskObject( &pUnitDeviceIdGroup->aUnitDevices[i] ); if ( unitDisk.get() == NULL ) return FALSE; // // Validation of disks // if ( !unitDisk->GetInfoHandler()->IsBound() ) return FALSE; // ERROR : disk is not bound vtUnitDisks.push_back(unitDisk); } // // Unbind disks // for ( i=0; i < vtUnitDisks.size(); i++ ) { if ( !vtUnitDisks[i]->CanAccessExclusive() ) { // ERROR : cannot access disk exclusively return FALSE; } } try { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Open( TRUE ); } } catch ( CNDASException & ) { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Close(); } // ERROR : Fail to connect to disk return FALSE; } for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->UnBind( vtUnitDisks[i] ); } try { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->CommitDiskInfo(); } } catch ( CNDASException & ) { for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Close(); } // ERROR : Unexpected error while writing return FALSE; } for ( i=0; i < vtUnitDisks.size(); i++ ) { vtUnitDisks[i]->Close(); } return TRUE; }
INT32 CRAID4DiskObject::GetDirtyDisk() const { LAST_WRITTEN_SECTORS Base, Compare; BOOL bIsDirty; INT32 iDirtyDisk, i; if(size() < 3) return -1; CUnitDiskObjectPtr pUnitDisk; CUnitDiskInfoHandlerPtr pUnitDiskHandler; std::list<CDiskObjectPtr>::iterator it; bIsDirty = FALSE; i = 0; iDirtyDisk = -2; // checking bitmaps for(it = begin(); it != end(); ++it, i++) { pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it); if(::IsEmptyDisk(pUnitDisk)) return -1; pUnitDiskHandler = pUnitDisk->GetInfoHandler(); if(pUnitDiskHandler->IsPeerDirty()) { #ifdef RAID_CRITICAL_CHECK if(bIsDirty) return -1; #endif bIsDirty = TRUE; iDirtyDisk = (i == 0) ? size() -1 : i -1; // previous device is dirty } } // checking LWS // 1 pass INT32 iSuspect; INT32 nFailCnt; i = 0; nFailCnt = 0; for(it = begin(); it != end(); ++it, i++) { pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it); if(::IsEmptyDisk(pUnitDisk)) { return -1; } pUnitDiskHandler = pUnitDisk->GetInfoHandler(); if(!i) { if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Base)) return -1; continue; } if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Compare)) return -1; if(memcmp(&Base, &Compare, sizeof(Base))) { nFailCnt++; iSuspect = i; } } if(0 == nFailCnt) // all are same { return iDirtyDisk; } else if(1 == nFailCnt) { if(bIsDirty && iSuspect != iDirtyDisk) #ifdef RAID_CRITICAL_CHECK return -1; #else return iDirtyDisk; #endif return iSuspect; } else if(size() -1 == nFailCnt) // 1st device(0) is the suspect { iSuspect = 0; i = 1; for(it = begin(), ++it; it != end(); ++it) { pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it); if(::IsEmptyDisk(pUnitDisk)) { return -1; } pUnitDiskHandler = pUnitDisk->GetInfoHandler(); if(1 == i) { if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Base)) return -1; continue; } if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Compare)) return -1; if(memcmp(&Base, &Compare, sizeof(Base))) { #ifdef RAID_CRITICAL_CHECK return -1; #else return (-2 == iDirtyDisk) ? iSuspect : iDirtyDisk; #endif } i++; } // all the others are same if(bIsDirty && iSuspect != iDirtyDisk) #ifdef RAID_CRITICAL_CHECK return -1; #else return (-2 == iDirtyDisk) ? iSuspect : iDirtyDisk; #endif return iSuspect; } else // 2 or more devices are not same { #ifdef RAID_CRITICAL_CHECK return -1; #else return (-2 == iDirtyDisk) ? iSuspect : iDirtyDisk; #endif } }
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; }