void *GallocyServer::handle(int client_socket, struct sockaddr_in client_name) { Request *request = get_request(client_socket); request->peer_ip = utils::parse_internet_address(inet_ntoa(client_name.sin_addr)); Response *response = routes.match(request->uri)(request); if (send(client_socket, response->str().c_str(), response->size(), 0) == -1) { error_die("send"); } LOG_INFO(request->method << " " << request->uri << " - " << "HTTP " << response->status_code << " - " << inet_ntoa(client_name.sin_addr) << " " << request->headers["User-Agent"]); // Teardown request->~Request(); internal_free(request); response->~Response(); internal_free(response); shutdown(client_socket, SHUT_RDWR); close(client_socket); return nullptr; }
void internal_free(be_node * data) { if (data == NULL) return; if (data->type == BE_STR) { delete[] data->val.s.ptr; } if (data->type == BE_LIST) { for(int i = 0; i<data->val.l.count; i++) internal_free(&data->val.l.elements[i]); delete[] data->val.l.elements; } if (data->type == BE_DICT) { for(int i = 0; i < data->val.d.count; i++) { internal_free(&data->val.d.vals[i]); delete[] data->val.d.keys[i].ptr; } delete[] data->val.d.keys; delete[] data->val.d.vals; } }
TEST(RoutingTableTests, Functors) { using ArgList = gallocy::vector<gallocy::string>; RoutingTable<std::function<gallocy::http::Response *(ArgList *, gallocy::http::Request *)> > t; gallocy::http::Response *response = new (internal_malloc(sizeof(gallocy::http::Response))) gallocy::http::Response(); auto f = [response](ArgList *a, gallocy::http::Request *request) { gallocy::stringstream s; s << a->size(); response->body = s.str(); return response; }; t.register_handler("/foo", f); t.register_handler("/foo/<x>", f); t.register_handler("/foo/<x>/bar", f); t.register_handler("/foo/<x>/bar/<y>", f); t.register_handler("/foo/<x>/baz", f); t.register_handler("/foo/<x>/baz/<y>", f); ASSERT_EQ(t.match("/foo")(nullptr)->body, "0"); ASSERT_EQ(t.match("/foo/arg1")(nullptr)->body, "1"); ASSERT_EQ(t.match("/foo/arg1/bar")(nullptr)->body, "1"); ASSERT_EQ(t.match("/foo/arg1/bar/arg2")(nullptr)->body, "2"); ASSERT_EQ(t.match("/foo/arg1/baz")(nullptr)->body, "1"); ASSERT_EQ(t.match("/foo/arg1/baz/arg2")(nullptr)->body, "2"); internal_free(response); }
void *GallocyServer::handle_entry(void *arg) { struct RequestContext *ctx = reinterpret_cast<struct RequestContext *>(arg); void *ret = ctx->server->handle(ctx->client_socket, ctx->client_name); ctx->~RequestContext(); internal_free(ctx); return ret; }
void debug_free(void* pointer) { if (DebugCallsDisabled() || pointer == nullptr) { return g_dispatch->free(pointer); } ScopedDisableDebugCalls disable; internal_free(pointer); }
/** * Clear a hash map */ void _Hashmap_clear(void* _self) { pHashmap self = (pHashmap)_self; for(size_t i = 0; i < self->size; i++) { if (self->elems[i]) internal_free(self->elems[i]); self->elems[i] = NULL; } }
void _BigInteger_asString(pVMObject object, pVMFrame frame) { pVMBigInteger self = (pVMBigInteger)SEND(frame, pop); // temporary storage for the number string // use c99 snprintf-goodie int64_t bigint = SEND(self, get_embedded_biginteger); char* strbuf = (char*)internal_allocate(snprintf(0, 0, "%lld", bigint) +1); sprintf(strbuf, "%lld", bigint); SEND(frame, push, (pVMObject)Universe_new_string(strbuf)); internal_free(strbuf); }
/** * frees a list and its content as well */ void _List_deep_free(void* _self) { pList self = (pList)_self; if(self->head) { pListElem elem = self->head; for(pListElem elem2 = elem; elem2; elem=elem2) { elem2 = elem->next; SEND((pOOObject)(elem->data), free); SEND(elem, free); } } internal_free(self); }
Response *GallocyServer::route_append_entries(RouteArguments *args, Request *request) { gallocy::json request_json = request->get_json(); gallocy::vector<LogEntry> leader_entries; uint64_t leader_commit_index = request_json["leader_commit"]; uint64_t leader_prev_log_index = request_json["previous_log_index"]; uint64_t leader_prev_log_term = request_json["previous_log_term"]; uint64_t leader_term = request_json["term"]; uint64_t local_term = gallocy_state->get_current_term(); bool success = false; for (auto entry_json : request_json["entries"]) { // TODO(sholsapp): Implicit conversion issue. gallocy::string tmp = entry_json["command"]; uint64_t term = entry_json["term"]; Command command(tmp); LogEntry entry(command, term); leader_entries.push_back(entry); } if (leader_term < local_term) { LOG_INFO("Rejecting leader " << request->peer_ip << " because term is outdated (" << leader_term << ")"); success = false; } else { // if (leader_entries.size() > 0) { // LOG_INFO("Appending " << leader_entries.size() << " new entries!"); // } success = true; gallocy_state->set_current_term(leader_term); gallocy_state->set_state(RaftState::FOLLOWER); gallocy_state->set_voted_for(request->peer_ip); gallocy_state->get_timer()->reset(); } gallocy::json response_json = { { "peer", gallocy_config->address.c_str() }, { "term", gallocy_state->get_current_term() }, { "success", success }, }; Response *response = new (internal_malloc(sizeof(Response))) Response(); response->headers["Server"] = "Gallocy-Httpd"; response->headers["Content-Type"] = "application/json"; response->status_code = 200; response->body = response_json.dump(); args->~RouteArguments(); internal_free(args); return response; }
void* internal_realloc(void *ptr, size_t size) { if (ptr == NULL) return internal_alloc(size, DEFAULT_ALIGNMENT); if (size == 0) return nullptr; void* new_data = NULL; auto head = get_block_header(ptr); if (size>0) new_data = internal_alloc(size, head->alignment); if (!new_data) return nullptr; mcpy(new_data, ptr, min(size, head->total_size - sizeof(block_header) - head->alignment + 1)); internal_free(ptr); return new_data; }
// TODO(sholsapp): This is just a route that we can hit to trigger an append // entries action. Once we're done testing, we can remove this route. Response *GallocyServer::route_request(RouteArguments *args, Request *request) { Command command("hello world"); LogEntry entry(command, gallocy_state->get_current_term()); gallocy::vector<LogEntry> entries; entries.push_back(entry); gallocy_client->send_append_entries(entries); Response *response = new (internal_malloc(sizeof(Response))) Response(); response->headers["Server"] = "Gallocy-Httpd"; response->headers["Content-Type"] = "application/json"; response->status_code = 200; response->body = "GOOD"; args->~RouteArguments(); internal_free(args); return response; }
Response *GallocyServer::route_request_vote(RouteArguments *args, Request *request) { gallocy::json request_json = request->get_json(); uint64_t candidate_commit_index = request_json["commit_index"]; uint64_t candidate_current_term = request_json["term"]; uint64_t candidate_last_applied = request_json["last_applied"]; uint64_t candidate_voted_for = request->peer_ip; uint64_t local_commit_index = gallocy_state->get_commit_index(); uint64_t local_current_term = gallocy_state->get_current_term(); uint64_t local_last_applied = gallocy_state->get_last_applied(); uint64_t local_voted_for = gallocy_state->get_voted_for(); bool granted = false; if (candidate_current_term < local_current_term) { granted = false; } else if (local_voted_for == 0 || local_voted_for == candidate_voted_for) { if (candidate_last_applied >= local_last_applied && candidate_commit_index >= local_commit_index) { LOG_INFO("Granting vote to " << utils::unparse_internet_address(candidate_voted_for) << " in term " << candidate_current_term); gallocy_state->set_current_term(candidate_current_term); gallocy_state->set_voted_for(candidate_voted_for); gallocy_state->get_timer()->reset(); granted = true; } else { // TODO(sholsapp): Implement logic to reject candidates that don't have // an up to date log. LOG_ERROR("Handling of out-of-date log is unimplemented"); } } gallocy::json response_json = { { "peer", gallocy_config->address.c_str() }, { "term", gallocy_state->get_current_term() }, { "vote_granted", granted }, }; Response *response = new (internal_malloc(sizeof(Response))) Response(); response->headers["Server"] = "Gallocy-Httpd"; response->headers["Content-Type"] = "application/json"; response->status_code = 200; response->body = response_json.dump(); args->~RouteArguments(); internal_free(args); return response; }
void* malloc_intercept::internal_realloc(void *ptr, size_t size) { if (ptr == NULL) return internal_alloc(size, DEFAULT_ALIGNMENT); // I don't know what size of alignment to use when realloc is called on block allocated with posix_memalign // Let's just preserve old alignment block_header* old_blk = block_by_ptr(ptr); void* new_data = internal_alloc(size, old_blk->alignment); if (new_data == NULL) return NULL; memcpy(new_data, ptr, std::min(size, old_blk->data_size)); internal_free(ptr); return new_data; }
void _Hashmap_rehash(void* _self, size_t newSize) { pHashmap self = (pHashmap)_self; size_t oldSize = self->size; pHashmapElem* oldElems = self->elems; self->size = newSize; self->elems = (pHashmapElem*)internal_allocate( self->size * sizeof(pHashmapElem)); SEND(self, clear); for(size_t i = 0; i < oldSize; i++) if(oldElems[i]) { if(!attemptPut(self, oldElems[i], hashf(self, SEND(oldElems[i], key_hash)))) // not good, can't help Universe_error_exit("Hashmap overflow while rehashing.\n"); else oldElems[i] = NULL; } internal_free(oldElems); }
Response *GallocyServer::route_admin(RouteArguments *args, Request *request) { Response *response = new (internal_malloc(sizeof(Response))) Response(); response->status_code = 200; response->headers["Server"] = "Gallocy-Httpd"; response->headers["Content-Type"] = "application/json"; #if 0 gallocy::json j = { {"status", "GOOD" }, {"master", is_master}, {"peers", { } }, {"diagnostics", { // TODO(sholsapp): These names suck.. we should indicate that they are allocators. { "local_internal_memory", reinterpret_cast<uint64_t>(&local_internal_memory) }, { "shared_page_table", reinterpret_cast<uint64_t>(&shared_page_table) }, // TODO(sholsapp): Add the main application allocator here. } }, }; for (auto p : peer_info_table.all()) { gallocy::json peer_info = { {"id", p.id}, {"ip_address", p.ip_address}, {"first_seen", p.first_seen}, {"last_seen", p.last_seen}, }; j["peers"].push_back(peer_info); } response->body = j.dump(); #endif response->body = "GOOD"; args->~RouteArguments(); internal_free(args); return response; }
pVMClass VMClass_assemble(class_generation_context* cgc) { // build class class name const char* cgc_name = SEND(cgc->name, get_chars); char* ccname = (char*)internal_allocate(strlen(cgc_name) + 6 + 1); // 6: " class" strcpy(ccname, cgc_name); strcat(ccname, " class"); pVMSymbol ccname_sym = Universe_symbol_for(ccname); internal_free(ccname); // Load the super class pVMClass super_class = Universe_load_class(cgc->super_name); // Allocate the class of the resulting class pVMClass result_class = Universe_new_class(metaclass_class); // Initialize the class of the resulting class SEND(result_class, set_instance_fields, Universe_new_array_list(cgc->class_fields)); SEND(result_class, set_instance_invokables, Universe_new_array_list(cgc->class_methods)); SEND(result_class, set_name, ccname_sym); pVMClass super_mclass = SEND(super_class, get_class); SEND(result_class, set_super_class, super_mclass); // Allocate the resulting class pVMClass result = Universe_new_class(result_class); // Initialize the resulting class SEND(result, set_instance_fields, Universe_new_array_list(cgc->instance_fields)); SEND(result, set_instance_invokables, Universe_new_array_list(cgc->instance_methods)); SEND(result, set_name, cgc->name); SEND(result, set_super_class, super_class); return result; }
void* debug_realloc(void* pointer, size_t bytes) { if (DebugCallsDisabled()) { return g_dispatch->realloc(pointer, bytes); } ScopedDisableDebugCalls disable; if (pointer == nullptr) { return internal_malloc(bytes); } if (bytes == 0) { internal_free(pointer); return nullptr; } size_t real_size = bytes; if (g_debug->config().options & EXPAND_ALLOC) { real_size += g_debug->config().expand_alloc_bytes; if (real_size < bytes) { // Overflow. errno = ENOMEM; return nullptr; } } void* new_pointer; size_t prev_size; if (g_debug->need_header()) { if (bytes > Header::max_size()) { errno = ENOMEM; return nullptr; } Header* header = g_debug->GetHeader(pointer); if (header->tag != DEBUG_TAG) { LogTagError(header, pointer, "realloc"); return nullptr; } // Same size, do nothing. if (real_size == header->real_size()) { // Do not bother recording, this is essentially a nop. return pointer; } // Allocation is shrinking. if (real_size < header->usable_size) { header->size = real_size; if (*g_malloc_zygote_child) { header->set_zygote(); } if (g_debug->config().options & REAR_GUARD) { // Don't bother allocating a smaller pointer in this case, simply // change the header usable_size and reset the rear guard. header->usable_size = header->real_size(); memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value, g_debug->config().rear_guard_bytes); } // Do not bother recording, this is essentially a nop. return pointer; } // Allocate the new size. new_pointer = internal_malloc(bytes); if (new_pointer == nullptr) { errno = ENOMEM; return nullptr; } prev_size = header->usable_size; memcpy(new_pointer, pointer, prev_size); internal_free(pointer); } else { prev_size = g_dispatch->malloc_usable_size(pointer); new_pointer = g_dispatch->realloc(pointer, real_size); if (new_pointer == nullptr) { return nullptr; } } if (g_debug->config().options & FILL_ON_ALLOC) { size_t bytes = internal_malloc_usable_size(new_pointer); if (bytes > g_debug->config().fill_on_alloc_bytes) { bytes = g_debug->config().fill_on_alloc_bytes; } if (bytes > prev_size) { memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size), g_debug->config().fill_alloc_value, bytes - prev_size); } } return new_pointer; }
void locality_profile_destroy() { delete_hash_map(locality_profile.context_hash_map); internal_free(locality_profile.s2t_map); }
void _OOObject_free(void* _self) { internal_free(_self); }
void _free(be_node * data) { internal_free(data); delete data; }
void _Hashmap_free(void* _self) { SEND((pHashmap)_self, clear); internal_free(((pHashmap)_self)->elems); SUPER(OOObject, _self, free); }