CharBuf*
IxManager_make_snapshot_filename(IndexManager *self)
{
    VArray *files = Folder_List(self->folder);
    u32_t i, max;
    i32_t max_gen = 0;

    for (i = 0, max = VA_Get_Size(files); i < max; i++) {
        CharBuf *file = (CharBuf*)VA_Fetch(files, i);
        if (    CB_Starts_With_Str(file, "snapshot_", 9)
                && CB_Ends_With_Str(file, ".json", 5)
           ) {
            i32_t gen = IxFileNames_extract_gen(file);
            if (gen > max_gen) {
                max_gen = gen;
            }
        }
    }
    DECREF(files);

    {
        i32_t    new_gen = max_gen + 1;
        CharBuf *base_36 = StrHelp_to_base36(new_gen);
        CharBuf *snapfile = CB_newf("snapshot_%o.json", base_36);
        DECREF(base_36);
        return snapfile;
    }
}
Exemple #2
0
static void
test_List(TestBatch *batch)
{
    Folder     *folder = (Folder*)RAMFolder_new(NULL);
    FileHandle *fh;
    VArray     *list;
    CharBuf    *elem;

    Folder_MkDir(folder, &foo);
    Folder_MkDir(folder, &foo_bar);
    Folder_MkDir(folder, &foo_bar_baz);
    fh = Folder_Open_FileHandle(folder, &boffo, FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);
    fh = Folder_Open_FileHandle(folder, &banana, FH_CREATE | FH_WRITE_ONLY);
    DECREF(fh);

    list = Folder_List(folder, NULL);
    VA_Sort(list, NULL, NULL);
    TEST_INT_EQ(batch, VA_Get_Size(list), 3, "List");
    elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 0), CHARBUF);
    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&banana), 
        "List first file");
    elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 1), CHARBUF);
    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&boffo), 
        "List second file");
    elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 2), CHARBUF);
    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&foo), "List dir");
    DECREF(list);

    list = Folder_List(folder, &foo_bar);
    TEST_INT_EQ(batch, VA_Get_Size(list), 1, "List subdirectory contents");
    elem = (CharBuf*)DOWNCAST(VA_Fetch(list, 0), CHARBUF);
    TEST_TRUE(batch, elem && CB_Equals(elem, (Obj*)&baz), 
        "Just the filename");
    DECREF(list);

    DECREF(folder);
}
static void
S_do_consolidate(CompoundFileWriter *self, CompoundFileWriterIVARS *ivars) {
    UNUSED_VAR(self);
    Folder    *folder       = ivars->folder;
    Hash      *metadata     = Hash_new(0);
    Hash      *sub_files    = Hash_new(0);
    Vector    *files        = Folder_List(folder, NULL);
    Vector    *merged       = Vec_new(Vec_Get_Size(files));
    String    *cf_file      = (String*)SSTR_WRAP_UTF8("cf.dat", 6);
    OutStream *outstream    = Folder_Open_Out(folder, (String*)cf_file);
    bool       rename_success;

    if (!outstream) { RETHROW(INCREF(Err_get_error())); }

    // Start metadata.
    Hash_Store_Utf8(metadata, "files", 5, INCREF(sub_files));
    Hash_Store_Utf8(metadata, "format", 6,
                    (Obj*)Str_newf("%i32", CFWriter_current_file_format));

    Vec_Sort(files);
    for (uint32_t i = 0, max = Vec_Get_Size(files); i < max; i++) {
        String *infilename = (String*)Vec_Fetch(files, i);

        if (!Str_Ends_With_Utf8(infilename, ".json", 5)) {
            InStream *instream   = Folder_Open_In(folder, infilename);
            Hash     *file_data  = Hash_new(2);
            int64_t   offset, len;

            if (!instream) { RETHROW(INCREF(Err_get_error())); }

            // Absorb the file.
            offset = OutStream_Tell(outstream);
            OutStream_Absorb(outstream, instream);
            len = OutStream_Tell(outstream) - offset;

            // Record offset and length.
            Hash_Store_Utf8(file_data, "offset", 6,
                            (Obj*)Str_newf("%i64", offset));
            Hash_Store_Utf8(file_data, "length", 6,
                            (Obj*)Str_newf("%i64", len));
            Hash_Store(sub_files, infilename, (Obj*)file_data);
            Vec_Push(merged, INCREF(infilename));

            // Add filler NULL bytes so that every sub-file begins on a file
            // position multiple of 8.
            OutStream_Align(outstream, 8);

            InStream_Close(instream);
            DECREF(instream);
        }
    }

    // Write metadata to cfmeta file.
    String *cfmeta_temp = (String*)SSTR_WRAP_UTF8("cfmeta.json.temp", 16);
    String *cfmeta_file = (String*)SSTR_WRAP_UTF8("cfmeta.json", 11);
    Json_spew_json((Obj*)metadata, (Folder*)ivars->folder, cfmeta_temp);
    rename_success = Folder_Rename(ivars->folder, cfmeta_temp, cfmeta_file);
    if (!rename_success) { RETHROW(INCREF(Err_get_error())); }

    // Clean up.
    OutStream_Close(outstream);
    DECREF(outstream);
    DECREF(files);
    DECREF(metadata);
    /*
    HashIterator *iter = HashIter_new(sub_files);
    while (HashIter_Next(iter)) {
        String *merged_file = HashIter_Get_Key(iter);
        if (!Folder_Delete(folder, merged_file)) {
            String *mess = MAKE_MESS("Can't delete '%o'", merged_file);
            DECREF(sub_files);
            Err_throw_mess(ERR, mess);
        }
    }
    DECREF(iter);
    */
    DECREF(sub_files);
    for (uint32_t i = 0, max = Vec_Get_Size(merged); i < max; i++) {
        String *merged_file = (String*)Vec_Fetch(merged, i);
        if (!Folder_Delete(folder, merged_file)) {
            String *mess = MAKE_MESS("Can't delete '%o'", merged_file);
            DECREF(merged);
            Err_throw_mess(ERR, mess);
        }
    }
    DECREF(merged);
}