method(MCUnitTestCase, void, runTests, voida) { runtime_log("%s\n", "MCUnitTestCase runTests"); unsigned i; unsigned bye_key = hash("bye"); unsigned setUp_key = hash("setUp"); unsigned tearDown_key = hash("tearDown"); if(obj==null || cast(MCObject*, obj)->isa==null) return; runtime_log("%s\n", "MCUnitTestCase runTests before for loop"); mc_hashitem* amethod; for (i = 0; i < get_tablesize(cast(MCObject*, obj)->isa->table->level); i++) { //runtime_log("MCUnitTestCase runTests in for loop index:[%d]\n", i); amethod = cast(MCObject*, obj)->isa->table->items[i]; if(amethod->value.mcvoidptr!=null && i!=bye_key && i!=setUp_key && i!=tearDown_key){ runtime_log("%s\n", "MCUnitTestCase runTests hit a matched method"); if(obj==null){ error_log("MCUnitTestCase runTests this pointer is null\n"); } runMethodByPointer(obj, amethod); } } }
mc_message _self_response_to_h(const mo obj, const char* methodname, unsigned hashval) { //we will return a struct mc_hashitem* res; mc_message tmpmsg = {nil, nil}; if(obj == nil){ error_log("_self_response_to(obj) obj is nil. return {nil, nil}\n"); return tmpmsg; } if(obj->isa == nil){ error_log("_self_response_to(obj) obj->isa is nil. return {nil, nil}\n"); return tmpmsg; } if((res=get_item_byhash(&(obj->isa->table), hashval, methodname)) != nil){ tmpmsg.object = obj; tmpmsg.addr = res->value; runtime_log("return a message[%s/%s]\n", nameof(tmpmsg.object), methodname); return tmpmsg; }else{ runtime_log("self_response_to class[%s] can not response to method[%s]\n", nameof(obj), methodname); return tmpmsg; } }
mc_message _self_response_to_h(const mo obj, const char* methodname, MCHash hashval) { //we will return a struct mc_hashitem* res = mull; mc_message tmpmsg = {mull, mull}; if(obj == mull){ //no need to warning user return tmpmsg; } if(obj->isa == mull){ error_log("_self_response_to(obj, '%s') obj->isa is mull. return {mull, mull}\n", methodname); return tmpmsg; } if((res=get_item_byhash(obj->isa->table, hashval, methodname)) != mull){ tmpmsg.object = obj; tmpmsg.address = res->value.mcfuncptr; runtime_log("return a message[%s/%s]\n", nameof(obj), methodname); return tmpmsg; }else{ if (obj->nextResponder != mull) { return _self_response_to_h(obj->nextResponder, methodname, hashval); }else{ runtime_log("self_response_to class[%s] can not response to method[%s]\n", nameof(obj), methodname); if (MC_STRICT_MODE == 1) { exit(-1); }else{ return tmpmsg; } } } }
int _runtime() { MPI_Status probe_status; int probe_flag = 0; MPI_Status rcv_status; int i = 0; int *message_buffer; int message_buffer_size = 2; int message_size = 0; message_buffer = malloc(sizeof(MPI_INT ) * message_buffer_size); if (message_buffer == NULL ) { sprintf(log_buffer, "RUNTIME ERROR: Cannot allocate initial message_buffer."); runtime_log(ERROR_RUNTIME); return -1; } /* Barrier synch to check that all subsystems have been initialized */ MPI_Barrier(comm); while (!close_application) { probe_flag = 0; MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &probe_flag, &probe_status); if (probe_flag) { if (!probe_status.MPI_ERROR) { MPI_Get_count(&probe_status, MPI_INT, &message_size); if (message_size > message_buffer_size) { free(message_buffer); message_buffer = malloc(sizeof(MPI_INT ) * message_size); if (message_buffer == NULL ) { sprintf(log_buffer, "RUNTIME ERROR: Cannot allocate resized message_buffer."); runtime_log(ERROR_RUNTIME); return -1; } message_buffer_size = message_size; } MPI_Recv(message_buffer, message_size, MPI_INT, probe_status.MPI_SOURCE, probe_status.MPI_TAG, comm, &rcv_status); perform_receive_callback(message_buffer, message_size, probe_status.MPI_SOURCE, probe_status.MPI_TAG); } } perform_request_callback(); perform_timely_callbacks(); _perform_event(); i++; if (!probe_flag) { nanosleep(&tim, &tim2); } } free(message_buffer); _runtime_cleanup(); return 0; }
/* * Utility function to unregister a callback given it's handle */ int _consensus_based_tob_unregister_callback(int handle) { if ((callback[handle] == consensus_based_tob_dummy_callback) || (handle >= callback_num)) { sprintf(log_buffer, "CONSENSUS BASED TOB ERROR: Cannot unregister callback, handle does not correspond to any registered callback"); runtime_log(ERROR_TOB); return -1; } callback[handle] = consensus_based_tob_dummy_callback; sprintf(log_buffer, "CONSENSUS BASED TOB INFO: Callback %d unregistered", handle); runtime_log(DEBUG_TOB); return 0; }
/* * Utility function to register a callback and getting the related handle */ int _consensus_based_tob_register_callback(int (*callback_func)(int*, int, int), int* handle) { int i = 0; for (i = 0; i < MAX_CALLBACK_NUM; i++) { if (callback[i] == consensus_based_tob_dummy_callback) { callback[i] = callback_func; *handle = i; callback_num++; sprintf(log_buffer, "CONSENSUS BASED TOB INFO: Callback %d registered", i); runtime_log(DEBUG_TOB); return 0; } } sprintf(log_buffer, "CONSENSUS BASED TOB ERROR: Cannot register callback, no slot available"); runtime_log(ERROR_TOB); return -1; }
/* * Utility function to register a timely callbacks and getting the related handle */ int _runtime_register_timely_callback(int (*callback_func)(void), int* handle) { int i = 0; for (i = 0; i < MAX_CALLBACK_NUM; i++) { if (timely_callback[i] == NULL ) { timely_callback[i] = callback_func; *handle = i; timely_callback_num++; sprintf(log_buffer, "RUNTIME INFO: Timely callback %d registered", i); runtime_log(DEBUG_RUNTIME); return 0; } } sprintf(log_buffer, "RUNTIME ERROR: Cannot register timely callback, no slot available"); runtime_log(ERROR_RUNTIME); return -1; }
void test_cut_objdsc() { test_bp_init(); pushToTail(pool, b1); pushToTail(pool, b2); pushToTail(pool, b3); pushToTail(pool, b4); pushToTail(pool, b5); pushToTail(pool, b6); runtime_log("pool count should be 6:%d\n", count(pool)); cut(pool, deref(o6).block, &tb); runtime_log("pool count should be 5:%d\n", count(pool)); cut(pool, deref(o5).block, &tb); runtime_log("pool count should be 4:%d\n", count(pool)); cut(pool, deref(o4).block, &tb); runtime_log("pool count should be 3:%d\n", count(pool)); cut(pool, deref(o3).block, &tb); runtime_log("pool count should be 2:%d\n", count(pool)); cut(pool, deref(o2).block, &tb); runtime_log("pool count should be 1:%d\n", count(pool)); cut(pool, deref(o1).block, &tb); runtime_log("pool count should be 0:%d\n", count(pool)); test_bp_end(); }
void test_cut_asc() { test_bp_init(); pushToTail(pool, b1); pushToTail(pool, b2); pushToTail(pool, b3); pushToTail(pool, b4); pushToTail(pool, b5); pushToTail(pool, b6); runtime_log("pool count should be 6:%d\n", count(pool)); cut(pool, b1, &tb); runtime_log("pool count should be 5:%d\n", count(pool)); cut(pool, b2, &tb); runtime_log("pool count should be 4:%d\n", count(pool)); cut(pool, b3, &tb); runtime_log("pool count should be 3:%d\n", count(pool)); cut(pool, b4, &tb); runtime_log("pool count should be 2:%d\n", count(pool)); cut(pool, b5, &tb); runtime_log("pool count should be 1:%d\n", count(pool)); cut(pool, b6, &tb); runtime_log("pool count should be 0:%d\n", count(pool)); test_bp_end(); }
int _consensus_based_tob_rb_deliver(int *data, int count) { int* message = (int*) data; if (count < 3) { sprintf(log_buffer, "CONSENSUS BASED TOB ERROR: Message bad format"); runtime_log(ERROR_TOB); return -1; } int handle = message[0]; int id = message[1]; int real_sender = message[2]; int message_size = count - 3; if (handle < 0 || handle > callback_num) { sprintf(log_buffer, "CONSENSUS BASED TOB ERROR: Handle out of range: %d", handle); runtime_log(ERROR_TOB); return -1; } if (real_sender < 0 || real_sender >= num_procs) { sprintf(log_buffer, "CONSENSUS BASED TOB ERROR: Message sent by unkown sender."); runtime_log(ERROR_TOB); return -1; } sprintf(log_buffer, "CONSENSUS BASED TOB INFO: Received message \"%d\" of size %d with handle %d from process %d", message[1], count, handle, real_sender); runtime_log(DEBUG_TOB); print_data("CONSENSUS BASED TOB Received Message", "value", data, count, DEBUG_LOG_LEVEL); if (is_in_delivered(id, real_sender) == -1) return -1; add_to_unordered(id, real_sender, &message[3], message_size, handle); fflush(stdout); free(data); _consensus_based_tob_new_consensus_istance(); return 0; }
void test_getFromHead() { test_bp_init(); pushToTail(pool, b1); pushToTail(pool, b2); pushToTail(pool, b3); pushToTail(pool, b4); runtime_log("pool count should be 4:%d\n", count(pool)); getFromHead(pool); runtime_log("pool count should be 3:%d\n", count(pool)); getFromHead(pool); runtime_log("pool count should be 2:%d\n", count(pool)); getFromHead(pool); runtime_log("pool count should be 1:%d\n", count(pool)); getFromHead(pool); runtime_log("pool count should be 0:%d\n", count(pool)); test_bp_end(); }
mc_class* _load(const char* name, size_t objsize, MCLoaderPointer loader) { mc_class* aclass = findclass(name); //try lock spin lock trylock_global_classtable(); if (aclass == null) { //new a item aclass = alloc_mc_class(objsize); mc_hashitem* item = new_item(name, MCGenericVp(null), hash(name));//nil first package_by_item(item, aclass); (*loader)(aclass); //set item //MCBool isOverride, MCBool isFreeValue set_item(&mc_global_classtable, item, false, name); runtime_log("load a class[%s]\n", name); } else { runtime_log("find a class[%s]\n", name); } //unlock unlock_global_classtable(); return aclass; }
/* * upon event <rbBroadcast | m> * * Given a pointer to the message array, the number of elements in the array and handle, * it packs the message, self id and the handle into a new buffer. The message is sent to the other * processes through Best Effort BroadCast */ int _consensus_based_tob_send(int *message, int count, int handle) { sprintf(log_buffer, "CONSENSUS BASED TOB INFO: Registering message \"%d\" with handle %d", message[0], handle); runtime_log(DEBUG_TOB); // Copying the message, adding CONSENSUS BASED TOB callback. int * buffer = (int*) malloc(sizeof(int) * (count + 3)); buffer[0] = handle; buffer[1] = serial_number++; buffer[2] = my_rank; copy_to_array(&buffer[3], message, count); _eager_reliable_broadcast_send(buffer, count + 3, eager_reliable_broadcast_handle); free(buffer); return 0; }
MCInline mc_class* findclass(const char* name) { //create a class hashtable if (mc_global_classtable == null) mc_global_classtable = new_table(MCHashTableLevel1); //cache // mc_hashitem* cache = mc_global_classtable->cache; // if (cache && cache->key == name) { // return (mc_class*)(cache->value.mcvoidptr); // } mc_hashitem* item = get_item_byhash(mc_global_classtable, hash(name), name); if (item == null) return null; else runtime_log("findClass item key:%s, value:%p\n", item->key, item->value.mcvoidptr); return (mc_class*)(item->value.mcvoidptr); }
static void runMethodByPointer(MCUnitTestCase* obj, mc_hashitem* amethod) { ff(obj, setUp, null); runtime_log("%s\n", "runMethodByPointer start"); try{ _push_jump(response_to(cast(MCObject*, obj), amethod->key), null); //if exception generated, this line will never be reached } catch(MCAssertYESException){ error_log("MCAssertNOException\n"); } catch(MCAssertNOException){ error_log("MCAssertNOException\n"); } catch(MCAssertnullException){ error_log("MCAssertnullException\n"); } catch(MCAssertNotnullException){ error_log("MCAssertNotnullException\n"); } catch(MCAssertSameException){ error_log("MCAssertSameException\n"); } catch(MCAssertNotSameException){ error_log("MCAssertNotSameException\n"); } catch(MCAssertEqualsException){ error_log("MCAssertEqualsException\n"); } finally{ error_log("testcase: %s at method: [%s]\n", cast(MCObject*, obj)->isa->item->key, amethod->key); } ff(obj, tearDown, null); }
static int ref_count_down(MCObject* const obj) { for (;;) { if (obj == null) { error_log("recycle/release(null) do nothing.\n"); return REFCOUNT_ERR; } if (obj->ref_count == 0) { runtime_log("recycle/release(%s) count=0 return\n", nameof(obj)); return REFCOUNT_ERR; } if (obj->ref_count == REFCOUNT_NO_MM) { debug_log("ref_count is REFCOUNT_NO_MM manage by runtime. do nothing\n"); return REFCOUNT_NO_MM; } if (obj->isa == null) { error_log("recycle/release(obj) obj have no class linked. do nothing.\n"); return REFCOUNT_ERR; } #ifdef NO_ATOMIC obj->ref_count--; break; #else int oldcount, newcount; int *addr; addr = &(this->ref_count); oldcount = mc_atomic_get_integer(addr); newcount = oldcount; if (newcount > 0) newcount--; if (!mc_atomic_set_integer(addr, oldcount, newcount)) break; #endif } return obj->ref_count; }
int _runtime_init(int argc, char **argv, unsigned int flags) { if (initialized) return -1; int i = 0; tim.tv_sec = 0; tim.tv_nsec = 1000000L; /* start up MPI if necessary */ MPI_Initialized(&initialized); if (!initialized) { MPI_Init(&argc, &argv); } comm = MPI_COMM_WORLD; /* find out process rank */ MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); /* find out number of processes */ MPI_Comm_size(MPI_COMM_WORLD, &num_procs); logger_init(); cleanup_callback_num = 0; cleanup_callback = (int (**)(void)) malloc(sizeof(int (*)(void)) * MAX_CALLBACK_NUM); if (cleanup_callback == NULL ) { sprintf(log_buffer, "RUNTIME ERROR:Cannot allocate cleanup callback vector"); runtime_log(ERROR_RUNTIME); } for (i = 0; i < MAX_CALLBACK_NUM; i++) cleanup_callback[i] = NULL; receive_callback_num = 0; receive_callback = (int (**)(int*, int, int)) malloc(sizeof(int (*)(int*, int, int)) * MAX_CALLBACK_NUM); if (receive_callback == NULL ) { sprintf(log_buffer, "RUNTIME ERROR:Cannot allocate receive callback vector"); runtime_log(ERROR_RUNTIME); } for (i = 0; i < MAX_CALLBACK_NUM; i++) receive_callback[i] = NULL; request_callback_num = 0; request_callback = (int (**)(void)) malloc(sizeof(int (*)(void)) * MAX_CALLBACK_NUM); if (request_callback == NULL ) { sprintf(log_buffer, "RUNTIME ERROR:Cannot allocate request callback vector"); runtime_log(ERROR_RUNTIME); } for (i = 0; i < MAX_CALLBACK_NUM; i++) request_callback[i] = NULL; timely_callback_num = 0; timely_callback = (int (**)(void)) malloc(sizeof(int (*)(void)) * MAX_CALLBACK_NUM); if (timely_callback == NULL ) { sprintf(log_buffer, "RUNTIME ERROR:Cannot allocate timely callback vector"); runtime_log(ERROR_RUNTIME); } for (i = 0; i < MAX_CALLBACK_NUM; i++) timely_callback[i] = NULL; _event_queue_init(); _runtime_register_request_callback(_runtime_request_callback, &runtime_receive_handle); _get_application_layer_message_id(&application_layer_message_id); _send_id_to_application(application_layer_message_id); initialized = 1; return 0; }
/* * Initialization function * Allocates the callback and unordered datastructures */ int _consensus_based_tob_init(unsigned int flags) { if (initialized) return -1; sprintf(log_buffer, "CONSENSUS BASED TOB INFO: Initializing Total Order Broadcast"); runtime_log(INFO_TOB); _eager_reliable_broadcast_init(flags); _flooding_consensus_init(flags); callback_num = 0; callback = (int (**)(int*, int, int)) malloc(sizeof(int (*)(int*, int, int)) * MAX_CALLBACK_NUM); if (callback == NULL ) { sprintf(log_buffer, "CONSENSUS BASED TOB ERROR:Cannot allocate callback vector"); runtime_log(ERROR_TOB); } int i = 0; for (i = 0; i < MAX_CALLBACK_NUM; i++) callback[i] = consensus_based_tob_dummy_callback; proc_data_set = (proc_data**) malloc(sizeof(proc_data*) * num_procs); for (i = 0; i < num_procs; i++) { proc_data_set[i] = (proc_data*) malloc(sizeof(proc_data)); proc_data_set[i]->gc_threshold = (serialNumber*) malloc(sizeof(serialNumber)); initializeSerialNumber(proc_data_set[i]->gc_threshold); proc_data_set[i]->delivered_set = (delivered*) malloc(sizeof(delivered)); proc_data_set[i]->delivered_set->id = -1; proc_data_set[i]->delivered_set->next = NULL; } serial_number = 0; unordered_set = (unordered *) malloc(sizeof(unordered)); unordered_set->id = -1; unordered_set->callback_id = -1; unordered_set->size = 0; unordered_set->message = NULL; unordered_set->next = NULL; consensus_set = (consensus *) malloc(sizeof(consensus)); consensus_set->round = -1; consensus_set->decided_set_size = 0; consensus_set->decided_set = NULL; consensus_set->next = NULL; current_consensus_round = 0; next_deciding_consensus_round = 0; if (flags & USING_CONSENSUS_BASED_TOTAL_ORDER_BROADCAST) { _consensus_based_tob_register_callback(_consensus_based_tob_deliver_to_application_callback, &application_layer_handle); _runtime_register_request_callback(_consensus_based_tob_request_callback, &runtime_request_handle); _get_application_layer_message_id(&application_layer_message_id); _send_id_to_application(application_layer_message_id); } _eager_reliable_broadcast_register_callback(consensus_based_tob_rb_deliver_callback, &eager_reliable_broadcast_handle); _flooding_consensus_register_callback(consensus_based_tob_decided_callback, &flooding_consensus_handle); initialized = 1; return 0; }
void test_bp_end() { empty(pool); runtime_log("test_bp_end pool count should be 0:%d\n", count(pool)); }
method(MCUnitTestCase, void, tearDown, voida) { //tear down fixture runtime_log("----MCUnitTestCase tearDown\n"); }
method(MCUnitTestCase, void, setUp, voida) { //set up fixture runtime_log("----MCUnitTestCase setUp\n"); }
/* * Place holder for the callback vector, should not be invoked */ int consensus_based_tob_dummy_callback(int* message, int count, int sender) { sprintf(log_buffer, "CONSENSUS BASED TOB ERROR: Referenced callback is not registered"); runtime_log(ERROR_TOB); return -1; }
mc_message _response_to_h(const mo obj, const char* methodname, unsigned hashval, int strict) { mc_object* obj_iterator = obj; mc_object* obj_first_hit = nil; mc_hashitem* met_first_hit = nil; mc_hashitem* met_item = nil; int hit_count = 0; int iter_count = 0; //int max_iter = get_tablesize(5); int max_iter = 10000; mc_message tmpmsg = {nil, nil}; if(obj == nil || obj->isa == nil){ error_log("_response_to(obj) obj is nil or obj->isa is nil. return {nil, nil}\n"); return tmpmsg; } for(obj_iterator = obj; obj_iterator!= nil; obj_iterator = obj_iterator->super){ if(iter_count++ > max_iter){ error_log("iter_count>max but class still can not response to method\n"); break; } if((met_item=get_item_byhash(&(obj_iterator->isa->table), hashval, methodname)) != nil) { runtime_log("hit a method [%s/%d] to match [%s]\n", met_item->key, met_item->index, methodname); hit_count++; tmpmsg.object = obj_iterator; tmpmsg.addr = met_item->value; if(obj_first_hit==nil)obj_first_hit = obj_iterator; if(met_first_hit==nil)met_first_hit = met_item; //for the method key have conflicted with some super class in inherit tree if(hit_count>1){ if(hit_count==2){ //to support the "overide" feature of oop if(mc_compare_key(met_first_hit->key, methodname) == 0){ tmpmsg.object = obj_first_hit; tmpmsg.addr = met_first_hit->value; runtime_log("[first hit]return a message[%s/%s(%p/%p)]\n", tmpmsg.object->isa->item->key, methodname, tmpmsg.object, tmpmsg.addr); return tmpmsg;} } if(mc_compare_key(met_item->key, methodname) == 0){ tmpmsg.object = obj_iterator; runtime_log("[string equal]return a message[%s/%s]\n", tmpmsg.object->isa->item->key, methodname); return tmpmsg;} } } } if(hit_count==1) runtime_log("return a message[%s/%s]\n", nameof(tmpmsg.object), methodname); else if(hit_count==0) { if (strict!=2) error_log("class[%s] can not response to method[%s]\n", nameof(obj), methodname); if (strict==1) exit(1); } else { if (strict!=2) error_log("hit_count>1 but class still can not response to method\n"); if (strict==1) exit(1); } return tmpmsg; }