Skip to content

Commit

Permalink
More stable index-flipping for write ops
Browse files Browse the repository at this point in the history
  • Loading branch information
jackoalan committed Feb 3, 2017
1 parent 8ed773d commit 11d1c67
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 25 deletions.
4 changes: 2 additions & 2 deletions include/kabufuda/Card.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ class Card
char m_maker[3] = {'\0'};

void _swapEndian();
void _updateDirAndBat();
void _updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat);
void _updateChecksum();
File* _fileFromHandle(const FileHandle& fh) const;
void _deleteFile(File& f);
void _deleteFile(File& f, BlockAllocationTable& bat);

public:
Card();
Expand Down
63 changes: 40 additions & 23 deletions lib/kabufuda/Card.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Card::Card(Card&& other)

Card& Card::operator=(Card&& other)
{
commit();
if (m_fileHandle)
fclose(m_fileHandle);

memmove(__raw, other.__raw, BlockSize);
m_filename = std::move(other.m_filename);
m_fileHandle = other.m_fileHandle;
Expand Down Expand Up @@ -147,17 +151,19 @@ ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut)
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;
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;
BlockAllocationTable& updateBat = m_bats[m_currentBat];
updateBat = bat;
updateBat.m_updateCounter++;
updateBat.updateChecksum();
}

void Card::_updateChecksum()
Expand Down Expand Up @@ -189,16 +195,18 @@ ECardResult Card::createFile(const char* filename, size_t size,
if (!m_dirs[m_currentDir].hasFreeFile())
return ECardResult::NOENT;

_updateDirAndBat();
File* f = m_dirs[m_currentDir].getFirstFreeFile(m_game, m_maker, filename);
uint16_t block = m_bats[m_currentBat].allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks);
Directory dir = m_dirs[m_currentDir];
BlockAllocationTable bat = m_bats[m_currentBat];
File* f = dir.getFirstFreeFile(m_game, m_maker, filename);
uint16_t block = bat.allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks);
if (f && block != 0xFFFF)
{
f->m_modifiedTime = uint32_t(getGCTime());
f->m_firstBlock = block;
f->m_blockCount = neededBlocks;

handleOut = FileHandle(m_dirs[m_currentDir].indexForFile(f));
_updateDirAndBat(dir, bat);
return ECardResult::READY;
}

Expand Down Expand Up @@ -236,44 +244,50 @@ const char* Card::getFilename(const FileHandle& fh)
return f->m_filename;
}

void Card::_deleteFile(File& f)
void Card::_deleteFile(File& f, BlockAllocationTable& bat)
{
uint16_t block = f.m_firstBlock;
while (block != 0xFFFF)
{
/* TODO: add a fragmentation check */
uint16_t nextBlock = m_bats[m_currentBat].getNextBlock(block);
m_bats[m_currentBat].clear(block, 1);
uint16_t nextBlock = bat.getNextBlock(block);
bat.clear(block, 1);
block = nextBlock;
}
f = File();
}

void Card::deleteFile(const FileHandle& fh)
{
_updateDirAndBat();
_deleteFile(*m_dirs[m_currentDir].getFile(fh.idx));
Directory dir = m_dirs[m_currentDir];
BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*dir.getFile(fh.idx), bat);
_updateDirAndBat(dir, bat);
}

ECardResult Card::deleteFile(const char* filename)
{
_updateDirAndBat();
File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, filename);
Directory dir = m_dirs[m_currentDir];
File* f = dir.getFile(m_game, m_maker, filename);
if (!f)
return ECardResult::NOFILE;

_deleteFile(*f);
BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*f, bat);
_updateDirAndBat(dir, bat);
return ECardResult::READY;
}

ECardResult Card::deleteFile(uint32_t fileno)
{
_updateDirAndBat();
File* f = m_dirs[m_currentDir].getFile(fileno);
Directory dir = m_dirs[m_currentDir];
File* f = dir.getFile(fileno);
if (!f)
return ECardResult::NOFILE;

_deleteFile(*f);
BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*f, bat);
_updateDirAndBat(dir, bat);
return ECardResult::READY;
}

Expand All @@ -282,12 +296,13 @@ ECardResult Card::renameFile(const char* oldName, const char* newName)
if (strlen(newName) > 32)
return ECardResult::NAMETOOLONG;

_updateDirAndBat();
File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, oldName);
Directory dir = m_dirs[m_currentDir];
File* f = dir.getFile(m_game, m_maker, oldName);
if (!f)
return ECardResult::NOFILE;

strncpy(f->m_filename, newName, 32);
_updateDirAndBat(dir, m_bats[m_currentBat]);
return ECardResult::READY;
}

Expand Down Expand Up @@ -930,6 +945,8 @@ void Card::commit()
tmpBat.updateChecksum();
tmpBat.swapEndian();
fwrite(tmpBat.__raw, 1, BlockSize, m_fileHandle);

fflush(m_fileHandle);
}
}

Expand Down

0 comments on commit 11d1c67

Please sign in to comment.