More stable index-flipping for write ops

This commit is contained in:
Jack Andersen 2017-02-02 20:21:49 -10:00
parent 8ed773d16f
commit 11d1c676c4
2 changed files with 42 additions and 25 deletions

View File

@ -135,10 +135,10 @@ class Card
char m_maker[3] = {'\0'}; char m_maker[3] = {'\0'};
void _swapEndian(); void _swapEndian();
void _updateDirAndBat(); void _updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat);
void _updateChecksum(); void _updateChecksum();
File* _fileFromHandle(const FileHandle& fh) const; File* _fileFromHandle(const FileHandle& fh) const;
void _deleteFile(File& f); void _deleteFile(File& f, BlockAllocationTable& bat);
public: public:
Card(); Card();

View File

@ -46,6 +46,10 @@ Card::Card(Card&& other)
Card& Card::operator=(Card&& other) Card& Card::operator=(Card&& other)
{ {
commit();
if (m_fileHandle)
fclose(m_fileHandle);
memmove(__raw, other.__raw, BlockSize); memmove(__raw, other.__raw, BlockSize);
m_filename = std::move(other.m_filename); m_filename = std::move(other.m_filename);
m_fileHandle = other.m_fileHandle; m_fileHandle = other.m_fileHandle;
@ -147,17 +151,19 @@ ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut)
return ECardResult::READY; return ECardResult::READY;
} }
void Card::_updateDirAndBat() void Card::_updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat)
{ {
Directory updateDir = m_dirs[m_currentDir];
updateDir.m_updateCounter++;
m_dirs[!m_currentDir] = updateDir;
m_currentDir = !m_currentDir; m_currentDir = !m_currentDir;
Directory& updateDir = m_dirs[m_currentDir];
updateDir = dir;
updateDir.m_updateCounter++;
updateDir.updateChecksum();
BlockAllocationTable updateBat = m_bats[m_currentBat];
updateBat.m_updateCounter++;
m_bats[!m_currentBat] = updateBat;
m_currentBat = !m_currentBat; m_currentBat = !m_currentBat;
BlockAllocationTable& updateBat = m_bats[m_currentBat];
updateBat = bat;
updateBat.m_updateCounter++;
updateBat.updateChecksum();
} }
void Card::_updateChecksum() void Card::_updateChecksum()
@ -189,9 +195,10 @@ ECardResult Card::createFile(const char* filename, size_t size,
if (!m_dirs[m_currentDir].hasFreeFile()) if (!m_dirs[m_currentDir].hasFreeFile())
return ECardResult::NOENT; return ECardResult::NOENT;
_updateDirAndBat(); Directory dir = m_dirs[m_currentDir];
File* f = m_dirs[m_currentDir].getFirstFreeFile(m_game, m_maker, filename); BlockAllocationTable bat = m_bats[m_currentBat];
uint16_t block = m_bats[m_currentBat].allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks); File* f = dir.getFirstFreeFile(m_game, m_maker, filename);
uint16_t block = bat.allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks);
if (f && block != 0xFFFF) if (f && block != 0xFFFF)
{ {
f->m_modifiedTime = uint32_t(getGCTime()); f->m_modifiedTime = uint32_t(getGCTime());
@ -199,6 +206,7 @@ ECardResult Card::createFile(const char* filename, size_t size,
f->m_blockCount = neededBlocks; f->m_blockCount = neededBlocks;
handleOut = FileHandle(m_dirs[m_currentDir].indexForFile(f)); handleOut = FileHandle(m_dirs[m_currentDir].indexForFile(f));
_updateDirAndBat(dir, bat);
return ECardResult::READY; return ECardResult::READY;
} }
@ -236,14 +244,14 @@ const char* Card::getFilename(const FileHandle& fh)
return f->m_filename; return f->m_filename;
} }
void Card::_deleteFile(File& f) void Card::_deleteFile(File& f, BlockAllocationTable& bat)
{ {
uint16_t block = f.m_firstBlock; uint16_t block = f.m_firstBlock;
while (block != 0xFFFF) while (block != 0xFFFF)
{ {
/* TODO: add a fragmentation check */ /* TODO: add a fragmentation check */
uint16_t nextBlock = m_bats[m_currentBat].getNextBlock(block); uint16_t nextBlock = bat.getNextBlock(block);
m_bats[m_currentBat].clear(block, 1); bat.clear(block, 1);
block = nextBlock; block = nextBlock;
} }
f = File(); f = File();
@ -251,29 +259,35 @@ void Card::_deleteFile(File& f)
void Card::deleteFile(const FileHandle& fh) void Card::deleteFile(const FileHandle& fh)
{ {
_updateDirAndBat(); Directory dir = m_dirs[m_currentDir];
_deleteFile(*m_dirs[m_currentDir].getFile(fh.idx)); BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*dir.getFile(fh.idx), bat);
_updateDirAndBat(dir, bat);
} }
ECardResult Card::deleteFile(const char* filename) ECardResult Card::deleteFile(const char* filename)
{ {
_updateDirAndBat(); Directory dir = m_dirs[m_currentDir];
File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, filename); File* f = dir.getFile(m_game, m_maker, filename);
if (!f) if (!f)
return ECardResult::NOFILE; return ECardResult::NOFILE;
_deleteFile(*f); BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*f, bat);
_updateDirAndBat(dir, bat);
return ECardResult::READY; return ECardResult::READY;
} }
ECardResult Card::deleteFile(uint32_t fileno) ECardResult Card::deleteFile(uint32_t fileno)
{ {
_updateDirAndBat(); Directory dir = m_dirs[m_currentDir];
File* f = m_dirs[m_currentDir].getFile(fileno); File* f = dir.getFile(fileno);
if (!f) if (!f)
return ECardResult::NOFILE; return ECardResult::NOFILE;
_deleteFile(*f); BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*f, bat);
_updateDirAndBat(dir, bat);
return ECardResult::READY; return ECardResult::READY;
} }
@ -282,12 +296,13 @@ ECardResult Card::renameFile(const char* oldName, const char* newName)
if (strlen(newName) > 32) if (strlen(newName) > 32)
return ECardResult::NAMETOOLONG; return ECardResult::NAMETOOLONG;
_updateDirAndBat(); Directory dir = m_dirs[m_currentDir];
File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, oldName); File* f = dir.getFile(m_game, m_maker, oldName);
if (!f) if (!f)
return ECardResult::NOFILE; return ECardResult::NOFILE;
strncpy(f->m_filename, newName, 32); strncpy(f->m_filename, newName, 32);
_updateDirAndBat(dir, m_bats[m_currentBat]);
return ECardResult::READY; return ECardResult::READY;
} }
@ -930,6 +945,8 @@ void Card::commit()
tmpBat.updateChecksum(); tmpBat.updateChecksum();
tmpBat.swapEndian(); tmpBat.swapEndian();
fwrite(tmpBat.__raw, 1, BlockSize, m_fileHandle); fwrite(tmpBat.__raw, 1, BlockSize, m_fileHandle);
fflush(m_fileHandle);
} }
} }