Пример #1
0
static void
test_to_base36(TestBatchRunner *runner) {
    char buffer[StrHelp_MAX_BASE36_BYTES];
    StrHelp_to_base36(UINT64_MAX, buffer);
    TEST_STR_EQ(runner, "3w5e11264sgsf", buffer, "base36 UINT64_MAX");
    StrHelp_to_base36(1, buffer);
    TEST_STR_EQ(runner, "1", buffer, "base36 1");
    TEST_INT_EQ(runner, buffer[1], 0, "base36 NULL termination");
}
Пример #2
0
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;
    }
}
Пример #3
0
CharBuf*
IxManager_make_snapshot_filename(IndexManager *self)
{
    Folder *folder = (Folder*)CERTIFY(self->folder, FOLDER);
    DirHandle *dh = Folder_Open_Dir(folder, NULL);
    CharBuf *entry;
    uint64_t max_gen = 0;

    if (!dh) { RETHROW(INCREF(Err_get_error())); }
    entry = DH_Get_Entry(dh);
    while (DH_Next(dh)) {
        if (    CB_Starts_With_Str(entry, "snapshot_", 9)
            && CB_Ends_With_Str(entry, ".json", 5)
        ) {
            uint64_t gen = IxFileNames_extract_gen(entry);
            if (gen > max_gen) { max_gen = gen; }
        }
    }
    DECREF(dh);

    {
        uint64_t new_gen = max_gen + 1;
        char  base36[StrHelp_MAX_BASE36_BYTES];
        StrHelp_to_base36(new_gen, &base36);
        return CB_newf("snapshot_%s.json", &base36);
    }
}
Пример #4
0
String*
IxManager_Make_Snapshot_Filename_IMP(IndexManager *self) {
    IndexManagerIVARS *const ivars = IxManager_IVARS(self);
    Folder *folder = (Folder*)CERTIFY(ivars->folder, FOLDER);
    DirHandle *dh = Folder_Open_Dir(folder, NULL);
    uint64_t max_gen = 0;

    if (!dh) { RETHROW(INCREF(Err_get_error())); }
    while (DH_Next(dh)) {
        String *entry = DH_Get_Entry(dh);
        if (Str_Starts_With_Utf8(entry, "snapshot_", 9)
            && Str_Ends_With_Utf8(entry, ".json", 5)
           ) {
            uint64_t gen = IxFileNames_extract_gen(entry);
            if (gen > max_gen) { max_gen = gen; }
        }
        DECREF(entry);
    }
    DECREF(dh);

    uint64_t new_gen = max_gen + 1;
    char  base36[StrHelp_MAX_BASE36_BYTES];
    StrHelp_to_base36(new_gen, &base36);
    return Str_newf("snapshot_%s.json", &base36);
}
Пример #5
0
void
Indexer_prepare_commit(Indexer *self)
{
    VArray   *seg_readers     = PolyReader_Get_Seg_Readers(self->polyreader);
    uint32_t  num_seg_readers = VA_Get_Size(seg_readers);
    bool_t    merge_happened  = false;

    if ( !self->write_lock || self->prepared ) {
        THROW(ERR, "Can't call Prepare_Commit() more than once");
    }

    // Merge existing index data. 
    if (num_seg_readers) { 
        merge_happened = S_maybe_merge(self, seg_readers);
    }

    // Add a new segment and write a new snapshot file if... 
    if (   Seg_Get_Count(self->segment)      // Docs/segs added. 
        || merge_happened                        // Some segs merged. 
        || !Snapshot_Num_Entries(self->snapshot) // Initializing index. 
        || DelWriter_Updated(self->del_writer) 
    ) {
        Folder   *folder   = self->folder;
        Schema   *schema   = self->schema;
        Snapshot *snapshot = self->snapshot;
        CharBuf  *old_schema_name = S_find_schema_file(snapshot);
        uint64_t  schema_gen = old_schema_name
                             ? IxFileNames_extract_gen(old_schema_name) + 1
                             : 1;
        char      base36[StrHelp_MAX_BASE36_BYTES];
        CharBuf  *new_schema_name;
        
        StrHelp_to_base36(schema_gen, &base36);
        new_schema_name = CB_newf("schema_%s.json", base36);

        // Finish the segment, write schema file. 
        SegWriter_Finish(self->seg_writer);
        Schema_Write(schema, folder, new_schema_name);
        if (old_schema_name) {
            Snapshot_Delete_Entry(snapshot, old_schema_name);
        }
        Snapshot_Add_Entry(snapshot, new_schema_name);
        DECREF(new_schema_name);

        // Write temporary snapshot file. 
        DECREF(self->snapfile);
        self->snapfile = IxManager_Make_Snapshot_Filename(self->manager);
        CB_Cat_Trusted_Str(self->snapfile, ".temp", 5);
        Folder_Delete(folder, self->snapfile);
        Snapshot_Write_File(snapshot, folder, self->snapfile);

        self->needs_commit = true;
    }

    // Close reader, so that we can delete its files if appropriate. 
    PolyReader_Close(self->polyreader);

    self->prepared = true;
}
Пример #6
0
static void
S_cat_seg_name(CharBuf *seg_name, u32_t seg_num)
{
    CharBuf *base_36 = StrHelp_to_base36(seg_num);
    CB_Cat_Str(seg_name, "seg_", 4);
    CB_Cat(seg_name, base_36);
    DECREF(base_36);
}
Пример #7
0
void
Indexer_Prepare_Commit_IMP(Indexer *self) {
    IndexerIVARS *const ivars = Indexer_IVARS(self);
    Vector   *seg_readers     = PolyReader_Get_Seg_Readers(ivars->polyreader);
    size_t    num_seg_readers = Vec_Get_Size(seg_readers);
    bool      merge_happened  = false;

    if (!ivars->write_lock || ivars->prepared) {
        THROW(ERR, "Can't call Prepare_Commit() more than once");
    }

    // Merge existing index data.
    if (num_seg_readers) {
        merge_happened = S_maybe_merge(self, seg_readers);
    }

    // Add a new segment and write a new snapshot file if...
    if (Seg_Get_Count(ivars->segment)             // Docs/segs added.
        || merge_happened                        // Some segs merged.
        || !Snapshot_Num_Entries(ivars->snapshot) // Initializing index.
        || DelWriter_Updated(ivars->del_writer)
       ) {
        Folder   *folder   = ivars->folder;
        Schema   *schema   = ivars->schema;
        Snapshot *snapshot = ivars->snapshot;

        // Derive snapshot and schema file names.
        DECREF(ivars->snapfile);
        String *snapfile = IxManager_Make_Snapshot_Filename(ivars->manager);
        ivars->snapfile = Str_Cat_Trusted_Utf8(snapfile, ".temp", 5);
        DECREF(snapfile);
        uint64_t schema_gen = IxFileNames_extract_gen(ivars->snapfile);
        char base36[StrHelp_MAX_BASE36_BYTES];
        StrHelp_to_base36(schema_gen, &base36);
        String *new_schema_name = Str_newf("schema_%s.json", base36);

        // Finish the segment, write schema file.
        SegWriter_Finish(ivars->seg_writer);
        Schema_Write(schema, folder, new_schema_name);
        String *old_schema_name = S_find_schema_file(snapshot);
        if (old_schema_name) {
            Snapshot_Delete_Entry(snapshot, old_schema_name);
        }
        Snapshot_Add_Entry(snapshot, new_schema_name);
        DECREF(new_schema_name);

        // Write temporary snapshot file.
        Folder_Delete(folder, ivars->snapfile);
        Snapshot_Write_File(snapshot, folder, ivars->snapfile);

        ivars->needs_commit = true;
    }

    // Close reader, so that we can delete its files if appropriate.
    PolyReader_Close(ivars->polyreader);

    ivars->prepared = true;
}
Пример #8
0
String*
Seg_num_to_name(int64_t number) {
    char base36[StrHelp_MAX_BASE36_BYTES];
    if (number < 0) {
        THROW(ERR, "Arg can't be negative: %i64", number);
    }
    StrHelp_to_base36((uint64_t)number, &base36);
    return Str_newf("seg_%s", &base36);
}
Пример #9
0
void
Snapshot_Write_File_IMP(Snapshot *self, Folder *folder, String *path) {
    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
    Hash   *all_data = Hash_new(0);
    Vector *list     = Snapshot_List(self);

    // Update path.
    DECREF(ivars->path);
    if (path != NULL && Str_Get_Size(path) != 0) {
        ivars->path = Str_Clone(path);
    }
    else {
        String *latest = IxFileNames_latest_snapshot(folder);
        uint64_t gen = latest ? IxFileNames_extract_gen(latest) + 1 : 1;
        char base36[StrHelp_MAX_BASE36_BYTES];
        StrHelp_to_base36(gen, &base36);
        ivars->path = Str_newf("snapshot_%s.json", &base36);
        DECREF(latest);
    }

    // Don't overwrite.
    if (Folder_Exists(folder, ivars->path)) {
        THROW(ERR, "Snapshot file '%o' already exists", ivars->path);
    }

    // Sort, then store file names.
    Vec_Sort(list);
    Hash_Store_Utf8(all_data, "entries", 7, (Obj*)list);

    // Create a JSON-izable data structure.
    Hash_Store_Utf8(all_data, "format", 6,
                    (Obj*)Str_newf("%i32", (int32_t)Snapshot_current_file_format));
    Hash_Store_Utf8(all_data, "subformat", 9,
                    (Obj*)Str_newf("%i32", (int32_t)Snapshot_current_file_subformat));

    // Write out JSON-ized data to the new file.
    Json_spew_json((Obj*)all_data, folder, ivars->path);

    DECREF(all_data);
}
Пример #10
0
void
Snapshot_write_file(Snapshot *self, Folder *folder, const CharBuf *path)
{
    Hash   *all_data = Hash_new(0);
    VArray *list     = Snapshot_List(self);

    // Update path. 
    DECREF(self->path);
    if (path) {
        self->path = CB_Clone(path);
    }
    else {
        CharBuf *latest = IxFileNames_latest_snapshot(folder);
        uint64_t gen = latest ? IxFileNames_extract_gen(latest) + 1 : 1;
        char base36[StrHelp_MAX_BASE36_BYTES];
        StrHelp_to_base36(gen, &base36);
        self->path = CB_newf("snapshot_%s.json", &base36);
        DECREF(latest);
    }

    // Don't overwrite. 
    if (Folder_Exists(folder, self->path)) {
        THROW(ERR, "Snapshot file '%o' already exists", self->path);
    }

    // Sort, then store file names. 
    VA_Sort(list, NULL, NULL);
    Hash_Store_Str(all_data, "entries", 7, (Obj*)list);

    // Create a JSON-izable data structure. 
    Hash_Store_Str(all_data, "format", 6, 
        (Obj*)CB_newf("%i32", (int32_t)Snapshot_current_file_format) );
    Hash_Store_Str(all_data, "subformat", 9, 
        (Obj*)CB_newf("%i32", (int32_t)Snapshot_current_file_subformat) );

    // Write out JSON-ized data to the new file. 
    Json_spew_json((Obj*)all_data, folder, self->path);

    DECREF(all_data);
}
Пример #11
0
void
Snapshot_write_file(Snapshot *self, Folder *folder, const CharBuf *filename)
{
    Hash   *all_data = Hash_new(0);
    VArray *list     = Snapshot_List(self);

    /* Update filename. */
    DECREF(self->filename);
    if (filename) {
        self->filename = CB_Clone(filename);
    }
    else {
        CharBuf *latest = IxFileNames_latest_snapshot(folder);
        i32_t gen = latest ? IxFileNames_extract_gen(latest) + 1 : 1;
        CharBuf *base_36 = StrHelp_to_base36(gen);
        self->filename = CB_newf("snapshot_%o.json", base_36);
        DECREF(latest);
        DECREF(base_36);
    }

    /* Don't overwrite. */
    if (Folder_Exists(folder, self->filename)) {
        THROW("Snapshot file '%o' already exists", self->filename);
    }

    /* Sort, then store file names. */
    VA_Sort(list, NULL);
    Hash_Store_Str(all_data, "entries", 7, (Obj*)list);

    /* Create a JSON-izable data structure. */
    Hash_Store_Str(all_data, "format", 6, 
        (Obj*)CB_newf("%i32", (i32_t)Snapshot_current_file_format) );

    /* Write out JSON-ized data to the new file. */
    Json_spew_json((Obj*)all_data, folder, self->filename);

    DECREF(all_data);
}
Пример #12
0
CharBuf*
Seg_num_to_name(int64_t number) {
    char base36[StrHelp_MAX_BASE36_BYTES];
    StrHelp_to_base36(number, &base36);
    return CB_newf("seg_%s", &base36);
}