void CLanUnitDiskObject::MarkAllBitmap(BOOL bMarkDirty) { // For write operation, session must be // created in advance. ATLASSERT( m_session.IsLoggedIn(TRUE) != FALSE ); // TODO : We need to check whether the DISK_INFOMRATION_BLOCK is version 2 CBitmapSector bitmap; ::FillMemory( bitmap.GetData(), bitmap.GetCount() * LANSCSI_BLOCK_SIZE, (bMarkDirty)? 0xff : 0x00 ); try{ bitmap.WriteAccept( &m_session ); } catch( CNDASException &e ) { NDAS_THROW_EXCEPTION_CHAIN_STR( CDiskException, CDiskException::ERROR_FAIL_TO_MARK_BITMAP, _T("Fail to write bitmap"), e); } // Mark the disk as dirty m_pHandler->SetDirty(bMarkDirty); try { m_pHandler->CommitDiskInfo( &m_session ); } catch( CNDASException &e ) { NDAS_THROW_EXCEPTION_CHAIN_STR( CDiskException, CDiskException::ERROR_FAIL_TO_MARK_BITMAP, _T("Fail to update NDAS_DIB"), e); } }
void CMirrorWorkThread::Run() { ::ZeroMemory( &m_report, sizeof(NBSYNC_REPORT) ); m_report.nSize = sizeof(NBSYNC_REPORT); if ( m_nWorkType == NBSYNC_TYPE_REMIRROR && !m_bRebound ) { try{ Notify( NBSYNC_PHASE_REBIND ); RebindMirror(); } catch( CNDASException &e ) { e.PrintStackTrace(); // TODO : We need more detail... the reason. Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_MARK_BITMAP ); return; } } if ( m_nWorkType == NBSYNC_TYPE_ADDMIRROR && !m_bAdded ) { try { Notify( NBSYNC_PHASE_BIND ); AddMirror(); } catch( CNDASException &e ) { e.PrintStackTrace(); // TODO : We need more detail... the reason. Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_ADDMIRROR ); return; } } CSession sSource, sDest; CBitmapSector bitmapSector; const UNIT_DISK_LOCATION *pSourceLocation, *pDestLocation; pSourceLocation = m_pSource->GetLocation()->GetUnitDiskLocation(); pDestLocation = m_pDest->GetLocation()->GetUnitDiskLocation(); Notify( NBSYNC_PHASE_CONNECT ); try{ sSource.Connect( pSourceLocation->MACAddr ); sDest.Connect( pDestLocation->MACAddr ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_CONNECT ); return; } try{ sSource.Login( pSourceLocation->UnitNumber, TRUE ); sDest.Login( pSourceLocation->UnitNumber, TRUE ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_CONNECT ); return; } Notify( NBSYNC_PHASE_RETRIVE_BITMAP ); // // Get bitmap from the disk // try{ bitmapSector.ReadAccept( &sSource ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_READ_BITMAP ); return; } Notify( NBSYNC_PHASE_SYNCHRONIZE ); // // Copying blocks // CHDDDiskInfoHandler *pHandler; pHandler = dynamic_cast<CHDDDiskInfoHandler*>(m_pSource->GetInfoHandler().get()); ATLASSERT( pHandler != NULL ); int i, j, k; _int8 bitFlag; _int16 nBitmapSecCount; _int32 nSectorPerBit, nSectorPerByte; _int8 *pbBitmap; _int64 nTotalDirtySize; _int64 nProcessedDirtySize; CDataSector dataSector, bitmapUpdateSector; pbBitmap = bitmapSector.GetData(); nSectorPerBit = pHandler->GetSectorsPerBit(); nSectorPerByte = nSectorPerBit*8; nBitmapSecCount = static_cast<_int16>( pHandler->GetUserSectorCount() / (nSectorPerBit*BLOCK_SIZE*8) ); ATLASSERT( nBitmapSecCount <= bitmapSector.GetCount() ); dataSector.Resize(nSectorPerBit); ::ZeroMemory( bitmapUpdateSector.GetData(), bitmapUpdateSector.GetCount() * BLOCK_SIZE ); // Calculate total amount of sectors to copy nTotalDirtySize = 0; nProcessedDirtySize = 0; for ( i=0; i < nBitmapSecCount; i++ ) { for ( j=0; j < BLOCK_SIZE; j++ ) { bitFlag = pbBitmap[i*BLOCK_SIZE + j]; if ( bitFlag == 0x00 ) // flag is clean(since most flags can be clean, this can improve efficiency) { continue; } for ( k=0; k < sizeof(_int8)* 8; k++ ) { if ( (bitFlag & ( 0x01 << k )) != 0 ) nTotalDirtySize += nSectorPerBit; } } } NotifyTotalSize( pHandler->GetUserSectorCount(), nTotalDirtySize ); for ( i=0; i < nBitmapSecCount; i++ ) { for ( j=0; j < BLOCK_SIZE; j++ ) { bitFlag = pbBitmap[i*BLOCK_SIZE + j]; if ( bitFlag == 0x00 ) // flag is clean(since most flags can be clean, this can improve efficiency) { continue; } for ( k=0; k < sizeof(_int8)* 8; k++ ) { if ( IsStopped() ) { goto out; } // Sectors are mapped from LSB to MSB if ( (bitFlag & ( 0x01 << k )) != 0 ) { dataSector.SetLocation( (static_cast<_int64>(i*BLOCK_SIZE + j)*sizeof(_int8) + k)*nSectorPerBit ); try { dataSector.ReadAccept( &sSource ); dataSector.WriteAccept( &sDest ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_COPY ); return; } nProcessedDirtySize += nSectorPerBit; } NotifyProgressDirty( nProcessedDirtySize ); } // for ( k=0; ... } // for ( j=0; ... // Clean up bitmap if ( IsStopped() ) { goto out; } bitmapUpdateSector.SetLocation( bitmapSector.GetLocation() + static_cast<_int64>(i) ); try{ bitmapUpdateSector.WriteAccept( &sSource ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_UPDATE_BITMAP ); return; } NotifyProgress( static_cast<_int64>(i*BLOCK_SIZE + j) * 8 * nSectorPerBit ); } // for ( i=0; ... // In case the bitmap does not fit into sectors exactly. _int64 nProcessedSize = static_cast<_int64>(nBitmapSecCount) * BLOCK_SIZE * 8 * nSectorPerBit; if ( nProcessedSize < pHandler->GetUserSectorCount() ) { int nLeftSize = static_cast<int>(pHandler->GetUserSectorCount()-nProcessedSize); for ( i=0; i < nLeftSize; i++ ) { bitFlag = pbBitmap[nBitmapSecCount*BLOCK_SIZE + i/nSectorPerByte]; if ( IsStopped() ) { goto out; } if ( (bitFlag & (0x01 << (i%8))) != 0 ) { dataSector.SetLocation( static_cast<_int64>(nBitmapSecCount*BLOCK_SIZE + i)*nSectorPerBit ); try { dataSector.ReadAccept( &sSource ); dataSector.WriteAccept( &sDest ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_COPY ); return; } nProcessedDirtySize += nSectorPerBit; NotifyProgressDirty( nProcessedDirtySize ); } } bitmapUpdateSector.SetLocation( bitmapSector.GetLocation() + nBitmapSecCount ); try{ bitmapUpdateSector.WriteAccept( &sSource ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_UPDATE_BITMAP ); return; } NotifyProgress( pHandler->GetUserSectorCount() ); } sSource.Logout(); sDest.Logout(); sSource.Disconnect(); sDest.Disconnect(); try{ m_pSource->OpenExclusive(); m_pSource->SetDirty(FALSE); m_pSource->CommitDiskInfo( TRUE ); } catch( CNDASException &e ) { e.PrintStackTrace(); Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_FAIL_TO_CLEAR_DIRTYFLAG ); return; } Notify( NBSYNC_PHASE_FINISHED ); return; out: sSource.Logout(); sDest.Logout(); sSource.Disconnect(); sDest.Disconnect(); if ( IsStopped() ) Notify( NBSYNC_PHASE_FAILED, NBSYNC_ERRORCODE_STOPPED ); else Notify( NBSYNC_PHASE_FINISHED ); }