Beispiel #1
0
bool CAeonView::InitRows (const CString &sRecoveryFilespec, int *retiRowsRecovered, CString *retsError)

//	InitRows
//
//	Initializes the rows structure.

	{
	ASSERT(m_pRows == NULL);
	return LoadRecoveryFile(sRecoveryFilespec, &m_pRows, retiRowsRecovered, retsError);
	}
bool Par1Repairer::LoadOtherRecoveryFiles(string filename) {
	// Split the original PAR filename into path and name parts
	string path;
	string name;
	DiskFile::SplitFilename(filename, path, name);

	// Find the file extension
	string::size_type where = name.find_last_of('.');
	if (where != string::npos) {
		// remove it
		name = name.substr(0, where);
	}

	// Search for additional PAR files
	string wildcard = name + ".???";
	list<string> *files = new list<string>;
	DiskFile::FindFiles(files, path, wildcard, false);

	for (list<string>::const_iterator s=files->begin(); s!=files->end(); ++s) {
		string filename = *s;

		// Find the file extension
		where = filename.find_last_of('.');
		if (where != string::npos) {
			string tail = filename.substr(where+1);

			// Check the the file extension is the correct form
			if ((tail[0] == 'P' || tail[0] == 'p') &&
					(
						((tail[1] == 'A' || tail[1] == 'a') && (tail[2] == 'R' || tail[2] == 'r'))
						||
						(isdigit(tail[1]) && isdigit(tail[2]))
					)) {
				LoadRecoveryFile(filename);
			}
		}
	}

	delete files;

	return true;
}
// Load packets from any other PAR files whose names are given on the command line
bool Par1Repairer::LoadExtraRecoveryFiles(const list<CommandLine::ExtraFile> &extrafiles) {
	for (ExtraFileIterator i=extrafiles.begin(); i!=extrafiles.end(); i++) {
		string filename = i->FileName();

		// Find the file extension
		string::size_type where = filename.find_last_of('.');
		if (where != string::npos) {
			string tail = filename.substr(where+1);

			// Check the the file extension is the correct form
			if ((tail[0] == 'P' || tail[0] == 'p') &&
					(
						((tail[1] == 'A' || tail[1] == 'a') && (tail[2] == 'R' || tail[2] == 'r'))
						||
						(isdigit(tail[1]) && isdigit(tail[2]))
					)) {
				LoadRecoveryFile(filename);
			}
		}
	}

	return true;
}
Result Par1Repairer::Process(const CommandLine &commandline, bool dorepair) {
	// How noisy should we be
	noiselevel = commandline.GetNoiseLevel();

	// Do we want to purge par files on success ?
	bool purgefiles = commandline.GetPurgeFiles();

	// Get filesnames from the command line
	string par1filename = commandline.GetParFilename();
	const list<CommandLine::ExtraFile> &extrafiles = commandline.GetExtraFiles();

	// Determine the searchpath from the location of the main PAR file
	string name;
	DiskFile::SplitFilename(par1filename, searchpath, name);

	// Load the main PAR file
	if (!LoadRecoveryFile(searchpath + name))
		return eLogicError;

	// Load other PAR files related to the main PAR file
	if (!LoadOtherRecoveryFiles(par1filename))
		return eLogicError;

	// Load any extra PAR files specified on the command line
	if (!LoadExtraRecoveryFiles(extrafiles))
		return eLogicError;

	if (noiselevel > CommandLine::nlQuiet)
		cout << endl << "Verifying source files:" << endl << endl;

	// Check for the existence of and verify each of the source files
	if (!VerifySourceFiles())
		return eFileIOError;

	if (completefilecount<sourcefiles.size()) {
		if (noiselevel > CommandLine::nlQuiet)
			cout << endl << "Scanning extra files:" << endl << endl;

		// Check any other files specified on the command line to see if they are
		// actually copies of the source files that have the wrong filename
		if (!VerifyExtraFiles(extrafiles))
			return eLogicError;
	}

	// Find out how much data we have found
	UpdateVerificationResults();

	if (noiselevel > CommandLine::nlSilent)
		cout << endl;

	// Check the verification results and report the details
	if (!CheckVerificationResults())
		return eRepairNotPossible;

	// Are any of the files incomplete
	if (completefilecount<sourcefiles.size()) {
		// Do we want to carry out a repair
		if (dorepair) {
			if (noiselevel > CommandLine::nlSilent)
				cout << endl;

			// Rename any damaged or missnamed target files.
			if (!RenameTargetFiles())
				return eFileIOError;

			// Are we still missing any files
			if (completefilecount<sourcefiles.size()) {
				// Work out which files are being repaired, create them, and allocate
				// target DataBlocks to them, and remember them for later verification.
				if (!CreateTargetFiles())
					return eFileIOError;

				// Work out which data blocks are available, which need to be recreated,
				// and compute the appropriate Reed Solomon matrix.
				if (!ComputeRSmatrix()) {
					// Delete all of the partly reconstructed files
					DeleteIncompleteTargetFiles();
					return eFileIOError;
				}

				// Allocate memory buffers for reading and writing data to disk.
				if (!AllocateBuffers(commandline.GetMemoryLimit())) {
					// Delete all of the partly reconstructed files
					DeleteIncompleteTargetFiles();
					return eMemoryError;
				}
				if (noiselevel > CommandLine::nlSilent)
					cout << endl;

				// Set the total amount of data to be processed.
				progress = 0;
				totaldata = blocksize * sourcefiles.size() * verifylist.size();

				// Start at an offset of 0 within a block.
				u64 blockoffset = 0;
				while (blockoffset < blocksize) { // Continue until the end of the block.
					// Work out how much data to process this time.
					size_t blocklength = (size_t)min((u64)chunksize, blocksize-blockoffset);

					// Read source data, process it through the RS matrix and write it to disk.
					if (!ProcessData(blockoffset, blocklength)) {
						// Delete all of the partly reconstructed files
						DeleteIncompleteTargetFiles();
						return eFileIOError;
					}

					// Advance to the need offset within each block
					blockoffset += blocklength;
				}

				if (noiselevel > CommandLine::nlSilent)
					cout << endl << "Verifying repaired files:" << endl << endl;

				// Verify that all of the reconstructed target files are now correct
				if (!VerifyTargetFiles()) {
					// Delete all of the partly reconstructed files
					DeleteIncompleteTargetFiles();
					return eFileIOError;
				}
			}

			// Are all of the target files now complete?
			if (completefilecount<sourcefiles.size()) {
				cerr << "Repair Failed." << endl;
				return eRepairFailed;
			} else {
				if (noiselevel > CommandLine::nlSilent)
					cout << endl << "Repair complete." << endl;
			}
		} else {
			return eRepairPossible;
		}
	}

	if (purgefiles == true) {
		RemoveBackupFiles();
		RemoveParFiles();
	}

	return eSuccess;
}