Thursday, December 22, 2016

New use case identified.

The experiment in my test lab was so successful. Feeling good? Not too early. Things always not working when put into real environment. Just like the use case diagram below.
Figure 1: Files are captured into index file
Notice that the files are captured into a file (index file) but not a destination. There are 2 problems I need to solve when I draft this design:
  1. to let the program know there are some files has been removed and thus the copy in destination must remove as well. 
  2. file exist in destination path but not in source path are consider orphan file. I'm trying to prevent these orphan file being removed from destination path.
Here are the requirements during the capturing process:
  • First scan will be done on the destination location.
  • Next scan will be done on the origin location.
  • If the file shown in origin location, but missing in a destination location, put a plus sign to indicate this file need to be added in. During the sync process, the file will be copied to the destination.
  • If the file was missing in origin location, but shown in the destination location, put a minus sign to indicate the file need to be removed. During the sync process, the file will be removed from the destination.
This was a real damn hard work logic. First thing first, I'll load up the content of index files into memory called fileContent through the constructor, this is the only chance I can load them up into memory when the FilePath object got intialized.
void FilePath::captureExistingFile()
{
    std::ifstream indexFile(indexFilePath, ios_base::in);
    string line = "";
    while( std::getline(indexFile, line) ) {
        fileContent.insert(line);
    }
    indexFile.close();
}


class FilePath
{
...
...

private:
    set<string> fileContent;
    path rootPath;
    std::ofstream indexFile;
};

FilePath::FilePath(path thePath)
    : rootPath(thePath), searchDone(false)
{
    ...

    // capture the index file content into memory
    indexFilePath = rootPath + string(1, path::preferred_separator) + ((seperatorPos > 0) ? filename : converterX.to_bytes(thePath.wstring())) + ".i";

    if( exists(indexFilePath) ) {
        captureExistingFile();
        bFileExist = true;
    }

    indexFile.open(indexFilePath, ios_base::in | ios_base::out | ios_base::app);
}
That is for the requirement 1 and 2. To handle the requirement plus and minus flag, here is the work around:
void FilePath::captureFiles(path searchPath)
{
    bool bPlus = false, bMinus = false;
    vector<path> pathList;

    if (rootPath.size() == 0) {
        rootPath = searchPath;
    }

    if( exists(searchPath) ) {
        // capture the paths/files list under the source

        ...

        // scan through path and those files sit in that path
        // scan for files in sub directory if there is any sub directory in that path
        for(vector<path>::const_iterator it(pathList.begin()); it != pathList.end(); ++it) {

            ...

            file = file.substr(thePath.length() + 1, file.length());

            // remove the files when index file content is larger than actual path
            if( fileContent.size() > pathList.size() - 1 ) {
                set<string>::iterator result = std::find(std::begin(fileContent), std::end(fileContent), file);
                if( result != std::end(fileContent) ) {
                    fileContent.erase(file);
                    bMinus = true;
                }
            }
            // new file has arrive when index file does exists
            // this block wouldn't execute if the path has never been scan before
            else if( fileContent.size() != 0 ){
                set<string>::iterator result = std::find(std::begin(fileContent), std::end(fileContent), file);
                if( result == std::end(fileContent) ) {
                    bPlus = true;
                    fileContent.insert(file);
                }
                else {
                    continue;
                }
            }

            ...

            // it is a file
            else {
                fileSet.insert(file);

                string filename(file.begin(), file.end());

                if( bPlus ) {
                    bPlus = false;
                    indexFile << "+" << filename << endl;
                }
                else if( !bMinus ) {
                    bMinus = false;
                    indexFile << filename << endl;
                }
            }
        }
    }

    indexFile.close();

    // there are some files has been remove
    // replace the content of index file
    if( bFileExist && bMinus ) {
        indexFile.open(indexFilePath, ios_base::out | ios_base::trunc);
        for( set<string>::iterator it=fileSet.begin(); it != fileSet.end(); it++ ) {
            indexFile << *it << endl;
        }

        for( set<string>::iterator it=fileContent.begin(); it != fileContent.end(); it++ ) {
            indexFile << "-" << *it << endl;
        }
    }

}
Sometimes I can't even remember my work after a few years not looking on my code, duh~

No comments: