Пример #1
0
bool
CFReader_Local_Delete_IMP(CompoundFileReader *self, String *name) {
    CompoundFileReaderIVARS *const ivars = CFReader_IVARS(self);
    Hash *record = (Hash*)Hash_Delete(ivars->records, name);
    DECREF(record);

    if (record == NULL) {
        return Folder_Local_Delete(ivars->real_folder, name);
    }
    else {
        // Once the number of virtual files falls to 0, remove the compound
        // files.
        if (Hash_Get_Size(ivars->records) == 0) {
            String *cf_file = (String*)SSTR_WRAP_UTF8("cf.dat", 6);
            if (!Folder_Delete(ivars->real_folder, cf_file)) {
                return false;
            }
            String *cfmeta_file = (String*)SSTR_WRAP_UTF8("cfmeta.json", 11);
            if (!Folder_Delete(ivars->real_folder, cfmeta_file)) {
                return false;

            }
        }
        return true;
    }
}
Пример #2
0
static void
Layer_Remove(int victim)
{
	LayerPtr	layer = (LayerPtr)Hash_Delete(layer_hash, victim);
	int			index;
	Widget		temp;
	int			i;

	for ( index = 0 ; layer_list_map[index] != victim ; index++ );

	free(layer->instances);
	free(layer->name);
	free(layer);

	temp = layer_toggles[index];
	XtUnmanageChild(temp);

	for ( i = index + 1; i < num_layers ; i++ )
	{
		layer_name_list[i-1] = layer_name_list[i];
		layer_list_map[i-1] = layer_list_map[i];
		layer_toggles[i-1] = layer_toggles[i];
	}
	num_layers--;
	layer_toggles[num_layers] = temp;
	XawListChange(layer_list_widget, layer_name_list, num_layers, 0, TRUE);
}
Пример #3
0
bool_t
CFReader_local_delete(CompoundFileReader *self, const CharBuf *name) {
    Hash *record = (Hash*)Hash_Delete(self->records, (Obj*)name);
    DECREF(record);

    if (record == NULL) {
        return Folder_Local_Delete(self->real_folder, name);
    }
    else {
        // Once the number of virtual files falls to 0, remove the compound
        // files.
        if (Hash_Get_Size(self->records) == 0) {
            CharBuf *cf_file = (CharBuf*)ZCB_WRAP_STR("cf.dat", 6);
            if (!Folder_Delete(self->real_folder, cf_file)) {
                return false;
            }
            CharBuf *cfmeta_file = (CharBuf*)ZCB_WRAP_STR("cfmeta.json", 11);
            if (!Folder_Delete(self->real_folder, cfmeta_file)) {
                return false;

            }
        }
        return true;
    }
}
Пример #4
0
bool_t
RAMFolder_local_delete(RAMFolder *self, const CharBuf *name)
{
    Obj *entry = Hash_Fetch(self->entries, (Obj*)name);
    if (entry) {
        if (Obj_Is_A(entry, RAMFILE)) {
            ;
        }
        else if (Obj_Is_A(entry, FOLDER)) {
            RAMFolder *inner_folder;
            if (Obj_Is_A(entry, COMPOUNDFILEREADER)) {
                inner_folder = (RAMFolder*)CERTIFY(
                    CFReader_Get_Real_Folder((CompoundFileReader*)entry), 
                    RAMFOLDER);
            }
            else {
                inner_folder = (RAMFolder*)CERTIFY(entry, RAMFOLDER);
            }
            if (Hash_Get_Size(inner_folder->entries)) {
                // Can't delete non-empty dir. 
                return false;
            }
        }
        else {
            return false;
        }
        DECREF(Hash_Delete(self->entries, (Obj*)name));
        return true;
    }
    else {
        return false;
    }
}
Пример #5
0
bool_t
RAMFolder_delete(RAMFolder *self, const CharBuf *filepath)
{
    RAMFileDes *file_des 
        = (RAMFileDes*)Hash_Delete(self->elems, filepath);
    if (file_des) { RAMFileDes_Dec_RefCount(file_des); }
    return !!file_des;
}
Пример #6
0
/* Gets the best node from OpenList
 *  returns the best node, or NULL of none is found
 * Also it deletes the node from the OpenList */
static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
{
	/* Return the item the Queue returns.. the best next OpenList item. */
	OpenListNode *res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
	if (res != NULL) {
		Hash_Delete(&aystar->OpenListHash, res->path.node.tile, res->path.node.direction);
	}

	return res;
}
Пример #7
0
bool_t
Snapshot_delete_entry(Snapshot *self, const CharBuf *entry)
{
    Obj *val = Hash_Delete(self->entries, entry);
    if (val) { 
        Obj_Dec_RefCount(val);
        return true;
    }
    else {
        return false;
    }
}
Пример #8
0
bool
Snapshot_Delete_Entry_IMP(Snapshot *self, String *entry) {
    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
    Obj *val = Hash_Delete(ivars->entries, entry);
    if (val) {
        DECREF(val);
        return true;
    }
    else {
        return false;
    }
}
Пример #9
0
void
RAMFolder_rename(RAMFolder *self, const CharBuf* from, const CharBuf *to)
{
    RAMFileDes *file_des = (RAMFileDes*)Hash_Delete(self->elems, from);

    if (file_des == NULL) {
        THROW("File '%o' not loaded into RAM", from);
    }

    Hash_Store(self->elems, to, (Obj*)file_des);
    FileDes_Set_Path(file_des, to);
}
Пример #10
0
bool
FSFolder_Local_Delete_IMP(FSFolder *self, String *name) {
    FSFolderIVARS *const ivars = FSFolder_IVARS(self);

    char *path_ptr = S_fullpath_ptr(self, name);
#ifdef CHY_REMOVE_ZAPS_DIRS
    bool result = !remove(path_ptr);
#else
    bool result = !rmdir(path_ptr) || !remove(path_ptr);
#endif
    DECREF(Hash_Delete(ivars->entries, (Obj*)name));
    FREEMEM(path_ptr);
    return result;
}
Пример #11
0
void* thread_code(void *arg)
{
  struct hash_job_desc *jd = (struct hash_job_desc *) arg;
  int numOfOps = NUM_OPS_PER_THREAD;
  int i = 0;
  int *addlist = malloc(sizeof(int) * numOfOps);
  if (addlist == NULL) {
    printf(" cannot allocate more ..., reduce space \n");
    exit(-1);
  }

  while (i < numOfOps) {
    //    addlist[i] = rand() % (numOfOps * num_threads);
    // since key is unique...
    addlist[i] = i + (numOfOps * jd->tid);
    Hash_Insert(&h, addlist + i, addlist[i]);
    (jd->ic)++;
    i++;
  }

  i = 0;
  while (i < numOfOps) {
    if (i % 3 == 0) {
      Hash_Delete(&h, addlist[i]);
      (jd->dc)++;
    }
    i++;
  }

  i = 0;
  while (i < numOfOps) {
    if (Hash_Lookup(&h, addlist[i]) != NULL)
      (jd->lc)++;
    i++;
  }


  //  printf("  END   Thread-%04d with %6d ic, %6d dc, %6d lc\n",
  //         jd->tid, jd->ic, jd->dc, jd->lc);

  free(addlist);

  return NULL;
}
Пример #12
0
int main ()
{

	FILE* the_table = fopen ("the_table.csv", "w");
	FILE* the_text = fopen ("the_text.txt", "r");

	assert (the_log);
	assert (the_table);
	assert (the_text);

	hash* the_hash = Hash_NEW();
	assert (the_hash);

	char word[MAXLEN] = {};
	int nWords = 0;
	typedef unsigned int (*hash_funcs) (const char* my_key);
	hash_funcs hf[5] = {hf0, hf1, hf2, hf3, hf4};
	int func_num = 0;
	char text_description[2 * MAXLEN] = {};
	strcpy (text_description, "Bradbury's novel \"Fahrenheit 451\"");

	OUT printf ("# This program allows to use hash-functions for sorting\n"
				"# words in %s\n"
                "# The developer:     Yura Gorishniy     <*****@*****.**>\n"
                "# Version 1.00\n"
                "# The file: %s\n"
                "# The compilation time: %s, %s\n\n", text_description, strrchr (__FILE__, '\\'), __DATE__, __TIME__);

	printf ("# You can use 5 hash-functions to analyse the novel:\n"
			"# Function [1]	hash = 0\n"
			"# Function [2]	hash = the ASCII code of the first letter of the word\n"
			"# Function [3]	hash = the sum of ASCII codes of all letters of the word\n"
			"# Function [4]	hash = the average ASCII code of all letters of the word\n"
			"# Function [5]	hash = the number, which we get after right cyclic shift\n"
			"# P.S. All the hashes you get will be counted by module %d\n\n", HASH_SIZE);

	printf ("# Please, enter number of the function you want to use\n");
	if (!scanf ("%d", &func_num))
	{
		printf ("Incorrect input, try again\n");
		abort ();
	}

	if (!(1 <= func_num && func_num <= 5))
		{
			printf ("Incorrect input, try again\n");
			abort ();
		}

	the_hash -> func = hf[func_num - 1];

	while (1)
	{
		if (get_word (the_text, word) == 0) break;
		nWords++;
		int hash = the_hash -> func (word) % the_hash -> size;
		elem* new_elem = NULL;
		List_Elem_Find_Key (the_hash -> table[hash], word, &new_elem);
		if (!new_elem) List_Elem_Add (the_hash -> table[hash], word, 1);
	}

	for (int i = 0; i < HASH_SIZE; ++i) fprintf (the_table, "%d\n", the_hash -> table[i] -> length);

	Hash_Dump (the_hash);
	Hash_Delete (the_hash);

	fclose (the_text);
	fclose (the_table);
	fclose (the_log);

	printf ("\nThe job is done! \nYou can use the_table.csv in Microsoft Excel to get a nice diagram\nGoodbye!\n\n");
	return 0;
}
Пример #13
0
static void
test_Store_and_Fetch(TestBatch *batch) {
    Hash          *hash         = Hash_new(100);
    Hash          *dupe         = Hash_new(100);
    const uint32_t starting_cap = Hash_Get_Capacity(hash);
    VArray        *expected     = VA_new(100);
    VArray        *got          = VA_new(100);
    ZombieCharBuf *twenty       = ZCB_WRAP_STR("20", 2);
    ZombieCharBuf *forty        = ZCB_WRAP_STR("40", 2);
    ZombieCharBuf *foo          = ZCB_WRAP_STR("foo", 3);

    for (int32_t i = 0; i < 100; i++) {
        CharBuf *cb = CB_newf("%i32", i);
        Hash_Store(hash, (Obj*)cb, (Obj*)cb);
        Hash_Store(dupe, (Obj*)cb, INCREF(cb));
        VA_Push(expected, INCREF(cb));
    }
    TEST_TRUE(batch, Hash_Equals(hash, (Obj*)dupe), "Equals");

    TEST_INT_EQ(batch, Hash_Get_Capacity(hash), starting_cap,
                "Initial capacity sufficient (no rebuilds)");

    for (int32_t i = 0; i < 100; i++) {
        Obj *key  = VA_Fetch(expected, i);
        Obj *elem = Hash_Fetch(hash, key);
        VA_Push(got, (Obj*)INCREF(elem));
    }

    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected),
              "basic Store and Fetch");
    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
                "size incremented properly by Hash_Store");

    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)foo) == NULL,
              "Fetch against non-existent key returns NULL");

    Hash_Store(hash, (Obj*)forty, INCREF(foo));
    TEST_TRUE(batch, ZCB_Equals(foo, Hash_Fetch(hash, (Obj*)forty)),
              "Hash_Store replaces existing value");
    TEST_FALSE(batch, Hash_Equals(hash, (Obj*)dupe),
               "replacement value spoils equals");
    TEST_INT_EQ(batch, Hash_Get_Size(hash), 100,
                "size unaffected after value replaced");

    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == (Obj*)foo,
              "Delete returns value");
    DECREF(foo);
    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
                "size decremented by successful Delete");
    TEST_TRUE(batch, Hash_Delete(hash, (Obj*)forty) == NULL,
              "Delete returns NULL when key not found");
    TEST_INT_EQ(batch, Hash_Get_Size(hash), 99,
                "size not decremented by unsuccessful Delete");
    DECREF(Hash_Delete(dupe, (Obj*)forty));
    TEST_TRUE(batch, VA_Equals(got, (Obj*)expected), "Equals after Delete");

    Hash_Clear(hash);
    TEST_TRUE(batch, Hash_Fetch(hash, (Obj*)twenty) == NULL, "Clear");
    TEST_TRUE(batch, Hash_Get_Size(hash) == 0, "size is 0 after Clear");

    DECREF(hash);
    DECREF(dupe);
    DECREF(got);
    DECREF(expected);
}
Пример #14
0
int main()
{
    pthread_t thread[3];
    counter_t counter;

    printf("Testing Counter...\n");

    printf("Begin single thread test\n");

    printf("Counter Init\n");
    Counter_Init(&counter, 0);

    printf("Counter_GetValue\n");
    int counter_val = Counter_GetValue(&counter);
    printf("expected 0 got %d\n", counter_val);

    printf("Counter_Increment\n");
    Counter_Increment(&counter);
    counter_val = counter_val = Counter_GetValue(&counter);
    printf("expected 1 got %d\n", counter_val);

    printf("Counter_Decrement\n");
    Counter_Decrement(&counter);
    counter_val = Counter_GetValue(&counter);
    printf("expected 0 got %d\n", counter_val);

    printf("Begin multithreaded test\n");

    printf("Counter Init\n");
    Counter_Init(&counter, 0);

    pthread_create(&thread[0], NULL, Counter_Increment, (void*)&counter);
    printf("Counter is at %d after 1 increment call\n", Counter_GetValue(&counter));
    pthread_create(&thread[1], NULL, Counter_Increment, (void*)&counter);
    printf("Counter is at %d after 2 increment calls\n", Counter_GetValue(&counter));
    pthread_create(&thread[2], NULL, Counter_Increment, (void*)&counter);
    printf("Counter is at %d after 3 increment calls\n", Counter_GetValue(&counter));

    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL);
    pthread_join(thread[2], NULL);

    printf("Count after 3 threads = %d\n", Counter_GetValue(&counter));

    printf("Done Testing Counter\n\n");

    list_insert_arg insert_arg[3];
    list_lookup_arg lookup_arg[3];
    list_t list;

    printf("Testing list...\n");

    printf("Begin single-thread test\n");

    printf("List_Init()\n");
    List_Init(&list);

    printf("List_Insert()\n");
    List_Insert(&list, (void *)0x1, 1);
    List_Insert(&list, (void *)0x2, 2);
    List_Insert(&list, (void *)0x3, 3);

    printf("Expected %p got %p\n", (void *)0x1, List_Lookup(&list, 1));
    printf("Expected %p got %p\n", (void *)0x3, List_Lookup(&list, 3));
    printf("Expected %p got %p\n", (void *)0x2, List_Lookup(&list, 2));

    printf("List_Delete()\n");
    List_Delete(&list, 1);

    printf("Expected %p got %p\n", (void *)0x2, List_Lookup(&list, 2));
    printf("Expected %p got %p\n", (void *)0x3, List_Lookup(&list, 3));
    printf("Expected %p got %p\n", NULL, List_Lookup(&list, 1));

    printf("Single-thread test completed\n");

    printf("Begin multi-thread test\n");

    printf("List_Init()\n");
    List_Init(&list);

    printf("Parallel List_Insert()\n");

    insert_arg[0].list = &list;
    insert_arg[0].element = (void *)0x1;
    insert_arg[0].key = 1;

    pthread_create(&thread[0], NULL, pthread_list_insert, &insert_arg[0]);

    insert_arg[1].list = &list;
    insert_arg[1].element = (void *)0x2;
    insert_arg[1].key = 2;

    pthread_create(&thread[1], NULL, pthread_list_insert, &insert_arg[1]);

    insert_arg[2].list = &list;
    insert_arg[2].element = (void *)0x3;
    insert_arg[2].key = 3;

    pthread_create(&thread[2], NULL, pthread_list_insert, &insert_arg[2]);

    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL);
    pthread_join(thread[2], NULL);

    printf("Parallel List_Insert() completed\n");

    printf("Parallel List_Lookup()\n");

    lookup_arg[0].list = &list;
    lookup_arg[0].key = 1;

    pthread_create(&thread[0], NULL, pthread_list_lookup, &lookup_arg[0]);

    lookup_arg[1].list = &list;
    lookup_arg[1].key = 2;

    pthread_create(&thread[1], NULL, pthread_list_lookup, &lookup_arg[1]);

    lookup_arg[2].list = &list;
    lookup_arg[2].key = 3;

    pthread_create(&thread[2], NULL, pthread_list_lookup, &lookup_arg[2]);

    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL);
    pthread_join(thread[2], NULL);

    printf("Parallel List_Lookup() completed\n");

    printf("List_Delete()\n");
    List_Delete(&list, 1);

    printf("Expected %p got %p\n", (void *)0x2, List_Lookup(&list, 2));
    printf("Expected %p got %p\n", (void *)0x3, List_Lookup(&list, 3));
    printf("Expected %p got %p\n", NULL, List_Lookup(&list, 1));

    printf("Multi-thread test completed\n");

    printf("Done testing list\n\n");

    hash_t hash;

    printf("Testing hash...\n");
    printf("Begin single-thread test\n");

    printf("Hash_Init()\n");
    Hash_Init(&hash, 2);

    printf("Hash_Insert()\n");
    Hash_Insert(&hash, (void *)0x1, 1);
    Hash_Insert(&hash, (void *)0x2, 2);
    Hash_Insert(&hash, (void *)0x3, 3);

    printf("Hash_Lookup()\n");
    printf("Expected %p got %p\n", (void *)0x2, Hash_Lookup(&hash, 2));
    printf("Expected %p got %p\n", (void *)0x3, Hash_Lookup(&hash, 3));
    printf("Expected %p got %p\n", (void *)0x1, Hash_Lookup(&hash, 1));

    printf("Hash_Delete()\n");
    Hash_Delete(&hash, 1);

    printf("Hash_Lookup()\n");
    printf("Expected %p got %p\n", (void *)0x2, Hash_Lookup(&hash, 2));
    printf("Expected %p got %p\n", (void *)0x3, Hash_Lookup(&hash, 3));
    printf("Expected %p got %p\n", NULL, Hash_Lookup(&hash, 1));

    printf("Single-thread test completed\n");
    printf("Done testing hash...\n");

    return 0;
}
Пример #15
0
static bool_t
S_rename_or_hard_link(RAMFolder *self, const CharBuf* from, const CharBuf *to,
                      Folder *from_folder, Folder *to_folder,
                      ZombieCharBuf *from_name, ZombieCharBuf *to_name,
                      int op)
{
    Obj       *elem              = NULL;
    RAMFolder *inner_from_folder = NULL;
    RAMFolder *inner_to_folder   = NULL;
    UNUSED_VAR(self);

    // Make sure the source and destination folders exist. 
    if (!from_folder) {
        Err_set_error(Err_new(CB_newf("File not found: '%o'", from)));
        return false;
    }
    if (!to_folder) {
        Err_set_error(Err_new(CB_newf(
            "Invalid file path (can't find dir): '%o'", to)));
        return false;
    }

    // Extract RAMFolders from compound reader wrappers, if necessary. 
    if (Folder_Is_A(from_folder, COMPOUNDFILEREADER)) {
        inner_from_folder = (RAMFolder*)CFReader_Get_Real_Folder(
            (CompoundFileReader*)from_folder);
    }
    else {
        inner_from_folder = (RAMFolder*)from_folder;
    }
    if (Folder_Is_A(to_folder, COMPOUNDFILEREADER)) {
        inner_to_folder = (RAMFolder*)CFReader_Get_Real_Folder(
            (CompoundFileReader*)to_folder);
    }
    else {
        inner_to_folder = (RAMFolder*)to_folder;
    }
    if (!RAMFolder_Is_A(inner_from_folder, RAMFOLDER)) {
        Err_set_error(Err_new(CB_newf("Not a RAMFolder, but a '%o'",
            Obj_Get_Class_Name((Obj*)inner_from_folder))));
        return false;
    }
    if (!RAMFolder_Is_A(inner_to_folder, RAMFOLDER)) {
        Err_set_error(Err_new(CB_newf("Not a RAMFolder, but a '%o'",
            Obj_Get_Class_Name((Obj*)inner_to_folder))));
        return false;
    }

    // Find the original element. 
    elem = Hash_Fetch(inner_from_folder->entries, (Obj*)from_name);
    if (!elem) {
        if (   Folder_Is_A(from_folder, COMPOUNDFILEREADER)
            && Folder_Local_Exists(from_folder, (CharBuf*)from_name)
        ) {
            Err_set_error(Err_new(CB_newf("Source file '%o' is virtual", 
                from)));
        }
        else {
            Err_set_error(Err_new(CB_newf("File not found: '%o'", from)));
        }
        return false;
    }

    // Execute the rename/hard-link. 
    if (op == OP_RENAME) {
        Obj *existing = Hash_Fetch(inner_to_folder->entries, (Obj*)to_name);
        if (existing) {
            bool_t conflict = false;

            // Return success fast if file is copied on top of itself. 
            if (   inner_from_folder == inner_to_folder 
                && ZCB_Equals(from_name, (Obj*)to_name)
            ) {
                return true;
            }

            // Don't allow clobbering of different entry type. 
            if (Obj_Is_A(elem, RAMFILE)) {
                if (!Obj_Is_A(existing, RAMFILE)) {
                    conflict = true;
                }
            }
            else if (Obj_Is_A(elem, FOLDER)) {
                if (!Obj_Is_A(existing, FOLDER)) {
                    conflict = true;
                }
            }
            if (conflict) {
                Err_set_error(Err_new(CB_newf("Can't clobber a %o with a %o",
                    Obj_Get_Class_Name(existing), Obj_Get_Class_Name(elem))));
                return false;
            }
        }

        // Perform the store first, then the delete. Inform Folder objects
        // about the relocation.
        Hash_Store(inner_to_folder->entries, (Obj*)to_name, INCREF(elem));
        DECREF(Hash_Delete(inner_from_folder->entries, (Obj*)from_name));
        if (Obj_Is_A(elem, FOLDER)) {
            CharBuf *newpath = S_fullpath(inner_to_folder, (CharBuf*)to_name);
            Folder_Set_Path((Folder*)elem, newpath);
            DECREF(newpath);
        }
    }
    else if (op == OP_HARD_LINK) {
        if (!Obj_Is_A(elem, RAMFILE)) {
            Err_set_error(Err_new(CB_newf("'%o' isn't a file, it's a %o",
                from, Obj_Get_Class_Name(elem))));
            return false;
        }
        else {
            Obj *existing 
                = Hash_Fetch(inner_to_folder->entries, (Obj*)to_name);
            if (existing) {
                Err_set_error(Err_new(CB_newf("'%o' already exists", to)));
                return false;
            }
            else {
                Hash_Store(inner_to_folder->entries, (Obj*)to_name, 
                    INCREF(elem));
            }
        }
    }
    else {
        THROW(ERR, "Unexpected op: %i32", (int32_t)op);
    }

    return true;
}
Пример #16
0
CompoundFileReader*
CFReader_do_open(CompoundFileReader *self, Folder *folder) {
    CharBuf *cfmeta_file = (CharBuf*)ZCB_WRAP_STR("cfmeta.json", 11);
    Hash *metadata = (Hash*)Json_slurp_json((Folder*)folder, cfmeta_file);
    Err *error = NULL;

    Folder_init((Folder*)self, Folder_Get_Path(folder));

    // Parse metadata file.
    if (!metadata || !Hash_Is_A(metadata, HASH)) {
        error = Err_new(CB_newf("Can't read '%o' in '%o'", cfmeta_file,
                                Folder_Get_Path(folder)));
    }
    else {
        Obj *format = Hash_Fetch_Str(metadata, "format", 6);
        self->format = format ? (int32_t)Obj_To_I64(format) : 0;
        self->records = (Hash*)INCREF(Hash_Fetch_Str(metadata, "files", 5));
        if (self->format < 1) {
            error = Err_new(CB_newf("Corrupt %o file: Missing or invalid 'format'",
                                    cfmeta_file));
        }
        else if (self->format > CFWriter_current_file_format) {
            error = Err_new(CB_newf("Unsupported compound file format: %i32 "
                                    "(current = %i32", self->format,
                                    CFWriter_current_file_format));
        }
        else if (!self->records) {
            error = Err_new(CB_newf("Corrupt %o file: missing 'files' key",
                                    cfmeta_file));
        }
    }
    DECREF(metadata);
    if (error) {
        Err_set_error(error);
        DECREF(self);
        return NULL;
    }

    // Open an instream which we'll clone over and over.
    CharBuf *cf_file = (CharBuf*)ZCB_WRAP_STR("cf.dat", 6);
    self->instream = Folder_Open_In(folder, cf_file);
    if (!self->instream) {
        ERR_ADD_FRAME(Err_get_error());
        DECREF(self);
        return NULL;
    }

    // Assign.
    self->real_folder = (Folder*)INCREF(folder);

    // Strip directory name from filepaths for old format.
    if (self->format == 1) {
        VArray *files = Hash_Keys(self->records);
        ZombieCharBuf *filename = ZCB_BLANK();
        ZombieCharBuf *folder_name
            = IxFileNames_local_part(Folder_Get_Path(folder), ZCB_BLANK());
        size_t folder_name_len = ZCB_Length(folder_name);

        for (uint32_t i = 0, max = VA_Get_Size(files); i < max; i++) {
            CharBuf *orig = (CharBuf*)VA_Fetch(files, i);
            if (CB_Starts_With(orig, (CharBuf*)folder_name)) {
                Obj *record = Hash_Delete(self->records, (Obj*)orig);
                ZCB_Assign(filename, orig);
                ZCB_Nip(filename, folder_name_len + sizeof(DIR_SEP) - 1);
                Hash_Store(self->records, (Obj*)filename, (Obj*)record);
            }
        }

        DECREF(files);
    }

    return self;
}
Пример #17
0
static void
S_discover_unused(FilePurger *self, VArray **purgables_ptr, 
                  VArray **snapshots_ptr)
{
    Folder      *folder       = self->folder;
    DirHandle   *dh           = Folder_Open_Dir(folder, NULL);
    if (!dh) { RETHROW(INCREF(Err_get_error())); }
    VArray      *spared       = VA_new(1);
    VArray      *snapshots    = VA_new(1);
    CharBuf     *snapfile     = NULL;

    // Start off with the list of files in the current snapshot.
    if (self->snapshot) {
        VArray *entries    = Snapshot_List(self->snapshot);
        VArray *referenced = S_find_all_referenced(folder, entries);
        VA_Push_VArray(spared, referenced);
        DECREF(entries);
        DECREF(referenced);
        snapfile = Snapshot_Get_Path(self->snapshot);
        if (snapfile) { VA_Push(spared, INCREF(snapfile)); }
    }

    CharBuf *entry      = DH_Get_Entry(dh);
    Hash    *candidates = Hash_new(64);
    while (DH_Next(dh)) {
        if      (!CB_Starts_With_Str(entry, "snapshot_", 9))   { continue; }
        else if (!CB_Ends_With_Str(entry, ".json", 5))         { continue; }
        else if (snapfile && CB_Equals(entry, (Obj*)snapfile)) { continue; }
        else {
            Snapshot *snapshot 
                = Snapshot_Read_File(Snapshot_new(), folder, entry);
            Lock *lock
                = IxManager_Make_Snapshot_Read_Lock(self->manager, entry);
            VArray *snap_list  = Snapshot_List(snapshot);
            VArray *referenced = S_find_all_referenced(folder, snap_list);

            // DON'T obtain the lock -- only see whether another
            // entity holds a lock on the snapshot file.
            if (lock) {
                Lock_Clear_Stale(lock);
            }
            if (lock && Lock_Is_Locked(lock)) {
                // The snapshot file is locked, which means someone's using
                // that version of the index -- protect all of its entries.
                uint32_t new_size = VA_Get_Size(spared) 
                                  + VA_Get_Size(referenced)  + 1;
                VA_Grow(spared, new_size);
                VA_Push(spared, (Obj*)CB_Clone(entry));
                VA_Push_VArray(spared, referenced);
            }
            else {
                // No one's using this snapshot, so all of its entries are
                // candidates for deletion.
                for (uint32_t i = 0, max = VA_Get_Size(referenced); i < max; i++) {
                    CharBuf *file = (CharBuf*)VA_Fetch(referenced, i);
                    Hash_Store(candidates, (Obj*)file, INCREF(&EMPTY));
                }
                VA_Push(snapshots, INCREF(snapshot));
            }

            DECREF(referenced);
            DECREF(snap_list);
            DECREF(snapshot);
            DECREF(lock);
        }
    }
    DECREF(dh);

    // Clean up after a dead segment consolidation.
    S_zap_dead_merge(self, candidates);

    // Eliminate any current files from the list of files to be purged.
    for (uint32_t i = 0, max = VA_Get_Size(spared); i < max; i++) {
        CharBuf *filename = (CharBuf*)VA_Fetch(spared, i);
        DECREF(Hash_Delete(candidates, (Obj*)filename));
    }

    // Pass back purgables and Snapshots.
    *purgables_ptr = Hash_Keys(candidates);
    *snapshots_ptr = snapshots;

    DECREF(candidates);
    DECREF(spared);
}
Пример #18
0
CompoundFileReader*
CFReader_do_open(CompoundFileReader *self, Folder *folder) {
    CompoundFileReaderIVARS *const ivars = CFReader_IVARS(self);
    String *cfmeta_file = (String*)SSTR_WRAP_UTF8("cfmeta.json", 11);
    Hash *metadata = (Hash*)Json_slurp_json((Folder*)folder, cfmeta_file);
    Err *error = NULL;

    Folder_init((Folder*)self, Folder_Get_Path(folder));

    // Parse metadata file.
    if (!metadata || !Hash_Is_A(metadata, HASH)) {
        error = Err_new(Str_newf("Can't read '%o' in '%o'", cfmeta_file,
                                 Folder_Get_Path(folder)));
    }
    else {
        Obj *format = Hash_Fetch_Utf8(metadata, "format", 6);
        ivars->format = format ? (int32_t)Obj_To_I64(format) : 0;
        ivars->records = (Hash*)INCREF(Hash_Fetch_Utf8(metadata, "files", 5));
        if (ivars->format < 1) {
            error = Err_new(Str_newf("Corrupt %o file: Missing or invalid 'format'",
                                     cfmeta_file));
        }
        else if (ivars->format > CFWriter_current_file_format) {
            error = Err_new(Str_newf("Unsupported compound file format: %i32 "
                                     "(current = %i32", ivars->format,
                                     CFWriter_current_file_format));
        }
        else if (!ivars->records) {
            error = Err_new(Str_newf("Corrupt %o file: missing 'files' key",
                                     cfmeta_file));
        }
    }
    DECREF(metadata);
    if (error) {
        Err_set_error(error);
        DECREF(self);
        return NULL;
    }

    // Open an instream which we'll clone over and over.
    String *cf_file = (String*)SSTR_WRAP_UTF8("cf.dat", 6);
    ivars->instream = Folder_Open_In(folder, cf_file);
    if (!ivars->instream) {
        ERR_ADD_FRAME(Err_get_error());
        DECREF(self);
        return NULL;
    }

    // Assign.
    ivars->real_folder = (Folder*)INCREF(folder);

    // Strip directory name from filepaths for old format.
    if (ivars->format == 1) {
        Vector *files = Hash_Keys(ivars->records);
        String *folder_name = IxFileNames_local_part(Folder_Get_Path(folder));
        size_t folder_name_len = Str_Length(folder_name);

        for (uint32_t i = 0, max = Vec_Get_Size(files); i < max; i++) {
            String *orig = (String*)Vec_Fetch(files, i);
            if (Str_Starts_With(orig, folder_name)) {
                Obj *record = Hash_Delete(ivars->records, orig);
                size_t offset = folder_name_len + sizeof(CHY_DIR_SEP) - 1;
                size_t len    = Str_Length(orig) - offset;
                String *filename = Str_SubString(orig, offset, len);
                Hash_Store(ivars->records, filename, (Obj*)record);
                DECREF(filename);
            }
        }

        DECREF(folder_name);
        DECREF(files);
    }

    return self;
}