static void program_scheduler_handle_error(ProgramScheduler *program_scheduler, bool log_as_error, const char *format, ...) { va_list arguments; char buffer[1024]; Program *program = containerof(program_scheduler, Program, scheduler); String *message; va_start(arguments, format); vsnprintf(buffer, sizeof(buffer), format, arguments); va_end(arguments); if (log_as_error) { log_error("Scheduler error for program object (identifier: %s) occurred: %s", program->identifier->buffer, buffer); } else { log_debug("Scheduler error for program object (identifier: %s) occurred: %s", program->identifier->buffer, buffer); } if (string_wrap(buffer, NULL, OBJECT_CREATE_FLAG_INTERNAL | OBJECT_CREATE_FLAG_LOCKED, NULL, &message) != API_E_SUCCESS) { message = NULL; } program_scheduler_stop(program_scheduler, message); }
static bool ver_done(jose_io_t *io) { io_t *i = containerof(io, io_t, io); const json_t *sig = NULL; uint8_t *buf = NULL; bool ret = false; size_t len = 0; sig = json_object_get(i->sig, "signature"); if (!sig) return false; len = jose_b64_dec(sig, NULL, 0); if (len == SIZE_MAX) return false; buf = malloc(len); if (!buf) return false; if (jose_b64_dec(sig, buf, len) != len) { free(buf); return false; } ret = EVP_DigestVerifyFinal(i->emc, buf, len) == 1; free(buf); return ret; }
static void tcp_close_cb(uv_handle_t *handle) { ls_tcp_t *tcp; lua_State *l, *nl; tcp = containerof(handle, ls_tcp_t, handle); l = ls_default_state(); if (ls_object_is_waited(&tcp->wait_object)) { int ref = tcp->wait_object.mthread_ref; tcp->wait_object.mthread_ref = LUA_NOREF; ls_getref(l, ref); nl = lua_tothread(l, -1); lua_pop(l, 1); if (nl) { ls_clear_waiting(nl); if (LUA_YIELD == lua_status(nl)) ls_error_resume(nl, LS_ERRCODE_EOF, "tcp closed"); } ls_unref(l, ref); } ls_free(l, tcp); }
void client_destroy(Client *client) { bool destroy_pending_requests = false; PendingRequest *pending_request; if (client->pending_request_count > 0) { log_warn("Destroying client ("CLIENT_SIGNATURE_FORMAT") while %d request(s) are still pending", client_expand_signature(client), client->pending_request_count); if (network_create_zombie(client) < 0) { log_error("Could not create zombie for %d pending request(s) of ("CLIENT_SIGNATURE_FORMAT")", client->pending_request_count, client_expand_signature(client)); destroy_pending_requests = true; } } writer_destroy(&client->response_writer); event_remove_source(client->io->handle, EVENT_SOURCE_TYPE_GENERIC); io_destroy(client->io); free(client->io); if (destroy_pending_requests) { while (client->pending_request_sentinel.next != &client->pending_request_sentinel) { pending_request = containerof(client->pending_request_sentinel.next, PendingRequest, client_node); pending_request_remove_and_free(pending_request); } } if (client->destroy_done != NULL) { client->destroy_done(); } }
static zx_status_t usb_midi_sink_write(void* ctx, const void* data, size_t length, zx_off_t offset, size_t* actual) { usb_midi_sink_t* sink = ctx; if (sink->dead) { return ZX_ERR_IO_NOT_PRESENT; } zx_status_t status = ZX_OK; size_t out_actual = length; const uint8_t* src = (uint8_t *)data; while (length > 0) { sync_completion_wait(&sink->free_write_completion, ZX_TIME_INFINITE); if (sink->dead) { return ZX_ERR_IO_NOT_PRESENT; } mtx_lock(&sink->mutex); list_node_t* node = list_remove_head(&sink->free_write_reqs); if (list_is_empty(&sink->free_write_reqs)) { sync_completion_reset(&sink->free_write_completion); } mtx_unlock(&sink->mutex); if (!node) { // shouldn't happen! status = ZX_ERR_INTERNAL; goto out; } usb_req_internal_t* req_int = containerof(node, usb_req_internal_t, node); usb_request_t* req = REQ_INTERNAL_TO_USB_REQ(req_int, sink->parent_req_size); size_t message_length = get_midi_message_length(*src); if (message_length < 1 || message_length > length) return ZX_ERR_INVALID_ARGS; uint8_t buffer[4]; buffer[0] = (src[0] & 0xF0) >> 4; buffer[1] = src[0]; buffer[2] = (message_length > 1 ? src[1] : 0); buffer[3] = (message_length > 2 ? src[2] : 0); usb_request_copy_to(req, buffer, 4, 0); req->header.length = 4; usb_request_complete_t complete = { .callback = usb_midi_sink_write_complete, .ctx = sink, }; usb_request_queue(&sink->usb, req, &complete); src += message_length; length -= message_length; } out: update_signals(sink); if (status == ZX_OK) { *actual = out_actual; } return status; }
static void tcp_read_cb(uv_stream_t *handle, ssize_t nread, uv_buf_t buf) { uv_loop_t *loop = uv_default_loop(); lua_State *l = ls_default_state(); ls_tcp_t *tcp = containerof(handle, ls_tcp_t, handle); lua_State *nl; if (ls_object_is_waited(&tcp->wait_object)) { int ref = tcp->wait_object.mthread_ref; ls_getref(l, ref); tcp->wait_object.mthread_ref = LUA_NOREF; nl = lua_tothread(l, -1); lua_pop(l, 1); if (nl) { ls_clear_waiting(nl); if (LUA_YIELD == lua_status(nl)) { if (nread == -1) ls_last_error_resume(nl, loop); else { lua_pushboolean(nl, 1); lua_pushlstring(nl, buf.base, nread); ls_resume(nl, 2); } } } ls_unref(l, ref); } }
// drop all pending requests for the given UID from the global list static void network_drop_pending_requests(uint32_t uid) { Node *pending_request_global_node = _pending_request_sentinel.next; Node *pending_request_global_node_next; PendingRequest *pending_request; char base58[BASE58_MAX_LENGTH]; int count = 0; while (pending_request_global_node != &_pending_request_sentinel) { pending_request = containerof(pending_request_global_node, PendingRequest, global_node); pending_request_global_node_next = pending_request_global_node->next; if (pending_request->header.uid == uid) { pending_request_remove_and_free(pending_request); ++count; } pending_request_global_node = pending_request_global_node_next; } if (count > 0) { log_warn("Dropped %d pending request(s) (uid: %s)", count, base58_encode(base58, uint32_from_le(uid))); } }
static zx_status_t session_io_cb(port_fd_handler_t* fh, unsigned pollevt, uint32_t evt) { vc_t* vc = containerof(fh, vc_t, fh); if (pollevt & POLLIN) { char data[1024]; ssize_t r = read(vc->fd, data, sizeof(data)); if (r > 0) { vc_write(vc, data, r, 0); return ZX_OK; } } if (pollevt & (POLLRDHUP | POLLHUP)) { // shell sessions get restarted on exit if (vc->is_shell) { zx_task_kill(vc->proc); vc->proc = ZX_HANDLE_INVALID; int fd = openat(vc->fd, "0", O_RDWR); if (fd < 0) { goto fail; } if (launch_shell(vc, fd, NULL) < 0) { goto fail; } return ZX_OK; } } fail: session_destroy(vc); return ZX_ERR_STOP; }
static u32 send_delta_block(int fd,int connfd) { u32 d_len; u64 d_off; u32 size_to_send = DELTA_BLOCK_ENTRY_SZ; delta_block_entry * dblk; list_head * dlst = dblk_link_list_head; if(dlst == NULL){ printf("no delta block to send!\n"); return 0; } while(1){ dblk = containerof(dlst,delta_block_entry,dbe_list); d_len = dblk->len; d_off = dblk->offset; if(dblk->dup_flag == N_DUP_BLOCK){ size_to_send += d_len; } lseek(fd,d_off,SEEK_SET); if(Read(fd,ptr,d_len) != d_len){ fprintf(stderr,"send_delta_block : less bytes read from fd!\n"); return 1; } memcpy(buf,dblk,DELTA_BLOCK_ENTRY_SZ); if(Write(connfd,buf,size_to_send) != size_to_send){ fprintf(stderr,"send_delta_block : less bytes written to socket!\n"); return 2; } if(IS_LAST_ENTRY(dlst)){ break; } dlst = dlst->next; } return 0; }
static void hsh_free(jose_io_t *io) { io_t *i = containerof(io, io_t, io); jose_io_decref(i->next); EVP_MD_CTX_free(i->emc); free(i); }
static void program_scheduler_handle_cron(void *opaque) { ProgramScheduler *program_scheduler = opaque; Program *program = containerof(program_scheduler, Program, scheduler); if (program_scheduler->state == PROGRAM_SCHEDULER_STATE_RUNNING && program->config.start_mode == PROGRAM_START_MODE_CRON) { program_scheduler_spawn_process(program_scheduler); } }
static void io_free(jose_io_t *io) { io_t *i = containerof(io, io_t, io); EVP_MD_CTX_free(i->emc); json_decref(i->obj); json_decref(i->sig); free(i); }
static void program_scheduler_handle_process_state_change(void *opaque) { ProgramScheduler *program_scheduler = opaque; Program *program = containerof(program_scheduler, Program, scheduler); bool spawn = false; if (program_scheduler->state != PROGRAM_SCHEDULER_STATE_RUNNING) { return; } if (program_scheduler->last_spawned_process->state == PROCESS_STATE_EXITED) { if (program_scheduler->last_spawned_process->exit_code == 0) { if (program->config.start_mode == PROGRAM_START_MODE_ALWAYS) { spawn = true; } } else { if (program->config.continue_after_error) { if (program->config.start_mode == PROGRAM_START_MODE_ALWAYS) { spawn = true; } } else { program_scheduler_stop(program_scheduler, NULL); } } } else if (program_scheduler->last_spawned_process->state == PROCESS_STATE_ERROR || program_scheduler->last_spawned_process->state == PROCESS_STATE_KILLED) { if (program->config.continue_after_error) { if (program->config.start_mode == PROGRAM_START_MODE_ALWAYS) { spawn = true; } } else { program_scheduler_stop(program_scheduler, NULL); } } if (spawn) { // delay next process spawn by 1 second to avoid running into a tight // loop of process spawn and process exit events which would basically // stop redapid from doing anything else. also if the throughput between // redapid and brickv is low then sending to many program-process-spawned // callbacks might force brickv into doing nothing else but updating // the last-spawned-program-process information if (timer_configure(&program_scheduler->timer, 1000000, 0) < 0) { program_scheduler_handle_error(program_scheduler, false, "Could not start timer: %s (%d)", get_errno_name(errno), errno); return; } log_debug("Started timer for program object (identifier: %s)", program->identifier->buffer); program_scheduler->timer_active = true; } }
static void program_scheduler_handle_timer(void *opaque) { ProgramScheduler *program_scheduler = opaque; Program *program = containerof(program_scheduler, Program, scheduler); if (program_scheduler->state == PROGRAM_SCHEDULER_STATE_RUNNING) { if (program->config.start_mode == PROGRAM_START_MODE_ALWAYS || program->config.start_mode == PROGRAM_START_MODE_INTERVAL) { program_scheduler_spawn_process(program_scheduler); } } }
void program_scheduler_continue(ProgramScheduler *program_scheduler) { Program *program = containerof(program_scheduler, Program, scheduler); if (program_scheduler->shutdown) { return; } if (program_scheduler->state == PROGRAM_SCHEDULER_STATE_STOPPED && program->config.start_mode != PROGRAM_START_MODE_NEVER) { program_scheduler_start(program_scheduler); } }
static void tcp_listen_cb(uv_stream_t *handle, int status) { lua_State *l = ls_default_state(); ls_tcp_t *server = containerof(handle, ls_tcp_t, handle); uv_loop_t *loop = uv_default_loop(); lua_State *nl; if (ls_object_is_waited(&server->wait_object)) { int ref = server->wait_object.mthread_ref; server->wait_object.mthread_ref = LUA_NOREF; ls_getref(l, ref); nl = lua_tothread(l, -1); lua_pop(l, 1); if (nl) { ls_clear_waiting(nl); if (status != 0) { ls_last_error_resume(nl, loop); } else { ls_tcp_t *client = new_tcp_handle(l); if (uv_accept(handle, (uv_stream_t*)&client->handle)) { ls_free(nl, client); luaL_error(nl, "accept failed"); } if (uv_read_start((uv_stream_t*)&client->handle, tcp_alloc_cb, tcp_read_cb)) { ls_free(nl, client); luaL_error(nl, "start read failed."); } if (LUA_YIELD == lua_status(nl)) { lua_pushboolean(nl, 1); new_tcp_connection_udata(nl, client); ls_resume(nl, 2); } else { ls_free(nl, client); } } } ls_unref(l, ref); } }
static bool hsh_done(jose_io_t *io) { io_t *i = containerof(io, io_t, io); uint8_t hsh[EVP_MD_CTX_size(i->emc)]; unsigned int l = 0; if (EVP_DigestFinal(i->emc, hsh, &l) <= 0) return SIZE_MAX; if (!i->next->feed(i->next, hsh, l) || !i->next->done(i->next)) return SIZE_MAX; return l; }
void program_scheduler_update(ProgramScheduler *program_scheduler, bool try_start) { APIE error_code; Program *program = containerof(program_scheduler, Program, scheduler); if (program_scheduler->shutdown) { return; } // check brickd connection state, if waiting for it if (program_scheduler->waiting_for_brickd && network_is_brickd_connected()) { program_scheduler->waiting_for_brickd = false; } // prepare filesystem error_code = program_scheduler_prepare_filesystem(program_scheduler); if (error_code != API_E_SUCCESS) { return; } if (!try_start) { // if starting should not be tried, then exit early return; } if (program->config.start_mode == PROGRAM_START_MODE_NEVER) { program_scheduler_stop(program_scheduler, program_scheduler->message); return; } if (program_scheduler->observer_state == PROCESS_OBSERVER_STATE_PENDING) { program_scheduler->observer_state = PROCESS_OBSERVER_STATE_WAITING; if (process_monitor_add_observer("lxpanel", 30, &program_scheduler->observer) < 0) { // if the observer could not be added, then start anyway. // this is still better than not starting at all program_scheduler->observer_state = PROCESS_OBSERVER_STATE_FINISHED; } } if (program_scheduler->observer_state == PROCESS_OBSERVER_STATE_FINISHED && !program_scheduler->waiting_for_brickd) { program_scheduler_start(program_scheduler); } }
void network_client_expects_response(Client *client, Packet *request) { PendingRequest *pending_request; char packet_signature[PACKET_MAX_SIGNATURE_LENGTH]; if (client->pending_request_count >= CLIENT_MAX_PENDING_REQUESTS) { log_warn("Pending requests list for client ("CLIENT_SIGNATURE_FORMAT") is full, dropping %d pending request(s)", client_expand_signature(client), client->pending_request_count - CLIENT_MAX_PENDING_REQUESTS + 1); while (client->pending_request_count >= CLIENT_MAX_PENDING_REQUESTS) { pending_request = containerof(client->pending_request_sentinel.next, PendingRequest, client_node); pending_request_remove_and_free(pending_request); } } pending_request = calloc(1, sizeof(PendingRequest)); if (pending_request == NULL) { log_error("Could not allocate pending request: %s (%d)", get_errno_name(ENOMEM), ENOMEM); return; } node_reset(&pending_request->global_node); node_insert_before(&_pending_request_sentinel, &pending_request->global_node); node_reset(&pending_request->client_node); node_insert_before(&client->pending_request_sentinel, &pending_request->client_node); ++client->pending_request_count; pending_request->client = client; pending_request->zombie = NULL; memcpy(&pending_request->header, &request->header, sizeof(PacketHeader)); #ifdef BRICKD_WITH_PROFILING pending_request->arrival_time = microseconds(); #endif log_packet_debug("Added pending request (%s) for client ("CLIENT_SIGNATURE_FORMAT")", packet_get_request_signature(packet_signature, request), client_expand_signature(client)); }
static void tcp_connect_cb(uv_connect_t *connect_req, int status) { ls_tcp_t *client = containerof(connect_req->handle, ls_tcp_t, handle); uv_tcp_t *handle = &client->handle; lua_State *l = ls_default_state(); lua_State *nl; uv_loop_t *loop = uv_default_loop(); ls_free(l, connect_req); if (ls_object_is_waited(&client->wait_object)) { int ref = client->wait_object.mthread_ref; client->wait_object.mthread_ref = LUA_NOREF; ls_getref(l, ref); nl = lua_tothread(l, -1); lua_pop(l, 1); if (nl) { ls_clear_waiting(nl); if (status) { uv_close((uv_handle_t*)handle, tcp_close_cb); ls_last_error_resume(nl, loop); } else { if (uv_read_start((uv_stream_t*)handle, tcp_alloc_cb, tcp_read_cb)) { uv_close((uv_handle_t*)handle, tcp_close_cb); ls_last_error_resume(nl, loop); } else { lua_pushboolean(nl, 1); new_tcp_connection_udata(nl, client); ls_resume(nl, 2); } } } ls_unref(l, ref); } }
static void free_dblk_list(void) { u8 last_dblk = 0; delta_block_entry * dblk; list_head * lst = dblk_link_list_head; if(lst == NULL) return; while(1){ dblk = containerof(lst,delta_block_entry,dbe_list); if(IS_LAST_ENTRY(lst)){ last_dblk = 1; } free(dblk); if(last_dblk == 1){ break; } lst = lst->next; } return; }
static bool sig_done(jose_io_t *io) { io_t *i = containerof(io, io_t, io); size_t len = 0; if (EVP_DigestSignFinal(i->emc, NULL, &len) <= 0) return false; uint8_t buf[len]; if (EVP_DigestSignFinal(i->emc, buf, &len) <= 0) return false; if (json_object_set_new(i->sig, "signature", jose_b64_enc(buf, len)) < 0) return false; return add_entity(i->obj, i->sig, "signatures", "signature", "protected", "header", NULL); }
static void tcp_write_cb(uv_write_t *req, int status) { ls_write_t *write_req = containerof(req, ls_write_t, req); uv_loop_t *loop = uv_default_loop(); lua_State *l, *nl; int i; l = ls_default_state(); for (i=0; i<write_req->refcnt; i++) { ls_unref(l, write_req->data_refs[i]); lua_pop(l, 1); write_req->data_refs[i] = LUA_NOREF; } write_req->refcnt = 0; if (ls_object_is_waited(&write_req->wait_object)) { int ref = write_req->wait_object.mthread_ref; write_req->wait_object.mthread_ref = LUA_NOREF; ls_getref(l, ref); nl = lua_tothread(l, -1); lua_pop(l, 1); if (nl) { ls_clear_waiting(nl); if (status) { ls_last_error_resume(nl, req->handle->loop); } else { ls_ok_resume(nl); } } ls_unref(l, ref); } ls_free(l, write_req); }
static void program_scheduler_stop(ProgramScheduler *program_scheduler, String *message) { static bool recursive = false; Program *program = containerof(program_scheduler, Program, scheduler); if (recursive) { return; } program_scheduler_abort_observer(program_scheduler); if (program_scheduler->timer_active) { if (timer_configure(&program_scheduler->timer, 0, 0) < 0) { recursive = true; program_scheduler_handle_error(program_scheduler, false, "Could not stop timer: %s (%d)", get_errno_name(errno), errno); recursive = false; } else { log_debug("Stopped timer for program object (identifier: %s)", program->identifier->buffer); program_scheduler->timer_active = false; } } if (program_scheduler->cron_active) { cron_remove_entry(program->base.id); log_debug("Removed cron entry for program object (identifier: %s)", program->identifier->buffer); program_scheduler->cron_active = false; } program_scheduler_set_state(program_scheduler, PROGRAM_SCHEDULER_STATE_STOPPED, time(NULL), message); }
/* returns process structure by its id */ process_t *proc_get_process_by_id(proc_id pid) { process_t *look4, *proc; unsigned int irqs_state; /* look for */ look4 = containerof(&pid, process_t, id); /* acquire lock before tree-search */ irqs_state = spin_lock_irqsave(&processes_lock); /* search */ proc = avl_tree_find(&processes_tree, look4, NULL); /* increment refs count on success search */ if(proc && proc->state != PROCESS_STATE_DEATH) atomic_inc((atomic_t*)&proc->ref_count); /* release lock */ spin_unlock_irqrstor(&processes_lock, irqs_state); return proc; }
static bool io_feed(jose_io_t *io, const void *in, size_t len) { io_t *i = containerof(io, io_t, io); return EVP_DigestUpdate(i->emc, in, len) > 0; }
int main() { /* rsync variables */ u8 file_name[FILE_NAME_LEN] = {'\0'}; u32 block_sz; u32 i; list_head ** lst_hd; list_head * lh_pre,* lh_next; u32 cblk_hash_v; /* chunk block */ u64 chunk_block_nr; chunk_file_header cfh; reply_to_chunk_file_header rplh; chunk_block_entry * cblk; chunk_block_entry * cblk_array; chunk_block_entry * cblk_p; chunk_block_entry * cblk_current; u64 chunk_block_no; u32 chunk_block_rollin_chksm; u32 chunk_block_len; u8 * chunk_block_md5; u32 brk_v; u32 is_first_entry,is_last_entry; /* searching for dup blocks */ u64 remaining_bytes; u64 delta_region_off; u64 dup_blk_off; u32 dup_blk_len; u32 rolling_chksm; u8 md5[MD5_SZ]; u32 n; u8 * p; u32 akl,bkl,skl; u8 dup_found; u8 oc,nc; /* file to sync */ int fd; struct stat file_stat; u64 file_sz; /* socket variables */ int port; int listenfd,connfd,len; char ip_str[INET_ADDRSTRLEN]; struct sockaddr_in addr,cli_addr; listenfd = socket(AF_INET,SOCK_STREAM,0); bzero(&addr,sizeof(addr)); addr.sin_family = AF_INET; inet_pton(AF_INET,RSYNC_HOST_IP,(void*)&addr.sin_addr); addr.sin_port = htons(RSYNC_SRV_PORT); len = sizeof(addr); bind(listenfd,(struct sockaddr *)&addr,len); listen(listenfd,LISTENQ); len = sizeof(cli_addr); connfd = accept(listenfd,(struct sockaddr *)&cli_addr,&len); bzero(ip_str,INET_ADDRSTRLEN); inet_ntop(AF_INET,(void*)&cli_addr.sin_addr,ip_str,INET_ADDRSTRLEN); port = ntohs(cli_addr.sin_port); printf(" from %s,port %d\n",ip_str,port); if(Read(connfd,&cfh,CHUNK_FILE_HEAD_SZ) != CHUNK_FILE_HEAD_SZ){ perror("read chunk_file_header"); goto over1; } printf("--------- read chunk_blk_header ok -----------\n"); block_sz = cfh.block_sz; chunk_block_nr = cfh.block_nr; strncpy(file_name,cfh.fn,strlen(cfh.fn)); printf("--- block_sz -- # %d\n",block_sz); printf("--- block_nr -- # %d\n",chunk_block_nr); printf("--- file_to_sync -- # %s\n",file_name); rplh.err = E_OK; if((fd = open(file_name,O_RDONLY)) < 0){ perror("open src file"); if(errno == ENOENT){ /* when file not exist,goto send_delta_file_header * need special disposition */ /* tell dst to delete file */ rplh.err = E_SRC_FILE_NOT_EXIST; goto SEND_RPL_TO_CFH; } goto over1; } if(fstat(fd,&file_stat) != 0){ perror("fstat"); goto over2; } file_sz = file_stat.st_size; if(file_sz == 0){ rplh.err = E_SRC_FILE_NO_BLK; } SEND_RPL_TO_CFH: /* send reply to chunk file header */ if(Write(connfd,&rplh,RPL_TO_CHUNK_FILE_HEADER_SZ) != RPL_TO_CHUNK_FILE_HEADER_SZ){ perror("write rpl to chunk file header"); goto over2; } if(rplh.err != E_OK){ goto over2; } /* dst file has 0 block */ if(chunk_block_nr == 0){ /* need special disposition */ printf("dst file has no block!\n"); update_delta_block_list(0,file_sz,0,NULL,block_sz); goto send_delta_file_header; } cblk_array = (chunk_block_entry*)malloc(chunk_block_nr*CHUNK_BLOCK_ENTRY_SZ); if(cblk_array == NULL){ perror("malloc for chunk_block_entry_array"); goto over2; } /* receive chunk block entry */ for(i = 0;i < chunk_block_nr;i++){ cblk_p = cblk_array + i; if(Read(connfd,cblk_p,CHUNK_BLOCK_ENTRY_SZ) != CHUNK_BLOCK_ENTRY_SZ){ perror("read chunk_block_entry"); goto over3; } chunk_block_rollin_chksm = cblk_p->rolling_chksm; chunk_block_len = cblk_p->block_len; chunk_block_md5 = cblk_p->md5; cblk_p->cbe_hash.next = &(cblk_p->cbe_hash); cblk_p->cbe_hash.pre = &(cblk_p->cbe_hash); cblk_hash_v = ROLLING_CHECKSUM_HASH(cblk_p->rolling_chksm); lst_hd = &chunk_blk_entry_hash[cblk_hash_v]; if(*lst_hd == NULL){ *lst_hd = &(cblk_p->cbe_hash); continue; } while(1){ brk_v = 0; cblk_current = containerof(*lst_hd,chunk_block_entry,cbe_hash); if(cblk_current->block_len == chunk_block_len && \ ROLLING_CHKSM_EQUAL(cblk_current->rolling_chksm,chunk_block_rollin_chksm)){ if(MD5_EQUAL(cblk_current->md5,chunk_block_md5)){ printf("skip identical chunk_block_entry\n"); brk_v = 1; break; } } if(cblk_current->rolling_chksm > chunk_block_rollin_chksm){ /* insert into the place before cblk_current */ brk_v = 2; break; } if(IS_LAST_ENTRY(*lst_hd)){ /* insert to tail */ brk_v = 3; break; } lst_hd = &((*lst_hd)->next); } switch(brk_v){ case 1: break; case 2: is_first_entry = 0; if(IS_FIRST_ENTRY(*lst_hd)){ is_first_entry = 1; }else{ lh_pre = (*lst_hd)->pre; } (*lst_hd)->pre = &(cblk_p->cbe_hash); cblk_p->cbe_hash.next = *lst_hd; if(is_first_entry == 1){ chunk_blk_entry_hash[cblk_hash_v] = &(cblk_p->cbe_hash); }else{ lh_pre->next = &(cblk_p->cbe_hash); cblk_p->cbe_hash.pre = lh_pre; } break; case 3: (*lst_hd)->next = &(cblk_p->cbe_hash); cblk_p->cbe_hash.pre = *lst_hd; break; default: break; } } printf("%d chunk block entrys received!\n",i); /* all chunk_block_entryS have been received * Now find the duplicate block from the src file */ dup_blk_off = 0; dup_blk_len = block_sz; delta_region_off = 0; /* initialize buffer */ buf_init(fd,file_sz); dup_found = DUP_FOUND; /* find duplicate block * and generate the list of delta_block */ while(dup_blk_off < file_sz){ n = 0; p = read_from_buf(dup_blk_off,dup_blk_len,&n); if(p == NULL){ fprintf(stderr,"some errors happened when read_from_buf\n"); goto over3; } /* else p is the pointer of the block * which is going to be checked * and the number of bytes is 'n' */ if(dup_found == DUP_FOUND){ /* start a new search or * current block is the last block of src_file */ printf("calculate the rolling_checksum with cal_rollin_cksm \n"); akl = 0,bkl = 0,skl = 0; skl = cal_rollin_cksm(p,&akl,&bkl,n); }else if(dup_found == DUP_NOT_FOUND){ /* the only case that rolling_checksum is calculated with last value */ printf("calculate the rolling_checksum with cal_rollin_cksm_plus_1 \n"); oc = *(p - 1); nc = (n < dup_blk_len?0:(*(p + n - 1))); skl = cal_rollin_cksm_plus_1(oc,nc,&akl,&bkl,dup_blk_len); } dup_found = DUP_NOT_FOUND; rolling_chksm = skl; cblk_hash_v = ROLLING_CHECKSUM_HASH(rolling_chksm); lst_hd = &(chunk_blk_entry_hash[cblk_hash_v]); /* searching */ if(*lst_hd == NULL){ /* no match, * right shift one byte and continue */ goto MODIFY_SOME_VAR_AND_GOTO_NEXT_LOOP; } while(1){ cblk_current = containerof(*lst_hd,chunk_block_entry,cbe_hash); if(cblk_current->block_len == n && \ ROLLING_CHKSM_EQUAL(cblk_current->rolling_chksm,rolling_chksm)){ /* same block_len and rolling_chksm, * need further checking md5 */ cal_md5(p,n,md5); if(MD5_EQUAL(cblk_current->md5,md5)){ dup_found = DUP_FOUND; break; } } if(cblk_current->rolling_chksm > rolling_chksm){ /* because collided chunk_blk_entry are sorted * no need to search further here */ break; } if(IS_LAST_ENTRY(*lst_hd)){ /* the last entry */ break; } lst_hd = &((*lst_hd)->next); } MODIFY_SOME_VAR_AND_GOTO_NEXT_LOOP: if(dup_found == DUP_FOUND){ /* dup_block found, * 1) make delta_block_entry list, * 2) reset : delta_region_off * delta_region_len * dup_blk_off * mention that dup_blk_off should be right shifted 'n' bytes */ update_delta_block_list(delta_region_off,dup_blk_off,n,cblk_current,dup_blk_len); dup_blk_off += n; delta_region_off = dup_blk_off; }else if(dup_found == DUP_NOT_FOUND){ /* dup_block not found, right shift one byte and continue */ dup_blk_off++; } } printf("finding dup_block over,delta_block_entry has been in the list!\n"); /* sending delta_file_header */ send_delta_file_header: dfh.block_nr = delta_block_nr; if(Write(connfd,&dfh,DELTA_FILE_HEADER_SZ) != DELTA_FILE_HEADER_SZ){ fprintf(stderr,"write delta_file_header fail!\n"); goto over3; } if(send_delta_block(fd,connfd) != 0){ fprintf(stderr,"some errors happened when sending delta_block!\n"); } over3: if(chunk_block_nr == 0){ goto over2; } free(cblk_array); over2: close(fd); over1: close(connfd); return 0; }
void client_dispatch_response(Client *client, PendingRequest *pending_request, Packet *response, bool force, bool ignore_authentication) { Node *pending_request_client_node = NULL; int enqueued = 0; #ifdef BRICKD_WITH_PROFILING uint64_t elapsed; #endif if (!ignore_authentication && client->authentication_state != CLIENT_AUTHENTICATION_STATE_DISABLED && client->authentication_state != CLIENT_AUTHENTICATION_STATE_DONE) { log_packet_debug("Ignoring non-authenticated client ("CLIENT_SIGNATURE_FORMAT")", client_expand_signature(client)); goto cleanup; } // find matching pending request if not forced and no pending request is // already given. do this before the disconnect check to ensure that even // for a disconnected client the pending request list is updated correctly if (!force && pending_request == NULL) { pending_request_client_node = client->pending_request_sentinel.next; while (pending_request_client_node != &client->pending_request_sentinel) { pending_request = containerof(pending_request_client_node, PendingRequest, client_node); if (packet_is_matching_response(response, &pending_request->header)) { break; } pending_request_client_node = pending_request_client_node->next; } if (pending_request_client_node == &client->pending_request_sentinel) { pending_request = NULL; goto cleanup; } } if (client->disconnected) { log_debug("Ignoring disconnected client ("CLIENT_SIGNATURE_FORMAT")", client_expand_signature(client)); goto cleanup; } if (force || pending_request != NULL) { enqueued = writer_write(&client->response_writer, response); if (enqueued < 0) { goto cleanup; } if (force) { log_packet_debug("Forced to %s response to client ("CLIENT_SIGNATURE_FORMAT")", enqueued ? "enqueue" : "send", client_expand_signature(client)); } else { #ifdef BRICKD_WITH_PROFILING elapsed = microseconds() - pending_request->arrival_time; log_packet_debug("%s response to client ("CLIENT_SIGNATURE_FORMAT"), was requested %u.%03u msec ago, %d request(s) still pending", enqueued ? "Enqueued" : "Sent", client_expand_signature(client), (unsigned int)(elapsed / 1000), (unsigned int)(elapsed % 1000), client->pending_request_count - 1); #else log_packet_debug("%s response to client ("CLIENT_SIGNATURE_FORMAT"), %d request(s) still pending", enqueued ? "Enqueued" : "Sent", client_expand_signature(client), client->pending_request_count - 1); #endif } } cleanup: if (pending_request != NULL) { pending_request_remove_and_free(pending_request); } }
static File *program_scheduler_prepare_stderr(ProgramScheduler *program_scheduler, struct timeval timestamp, File *stdout) { Program *program = containerof(program_scheduler, Program, scheduler); File *file; APIE error_code; switch (program->config.stderr_redirection) { case PROGRAM_STDIO_REDIRECTION_DEV_NULL: // FIXME: maybe only open /dev/null once and share it between all schedulers error_code = file_open(program_scheduler->dev_null_file_name->base.id, FILE_FLAG_WRITE_ONLY, 0, 1000, 1000, NULL, OBJECT_CREATE_FLAG_INTERNAL, NULL, &file); if (error_code != API_E_SUCCESS) { program_scheduler_handle_error(program_scheduler, false, "Could not open /dev/null for writing: %s (%d)", api_get_error_code_name(error_code), error_code); return NULL; } return file; case PROGRAM_STDIO_REDIRECTION_PIPE: // should never be reachable program_scheduler_handle_error(program_scheduler, true, "Invalid stderr redirection %d", program->config.stderr_redirection); return NULL; case PROGRAM_STDIO_REDIRECTION_FILE: if (program_scheduler->absolute_stderr_file_name == NULL) { // should never be reachable program_scheduler_handle_error(program_scheduler, true, "Absolute stderr file name not set"); return NULL; } error_code = file_open(program_scheduler->absolute_stderr_file_name->base.id, FILE_FLAG_WRITE_ONLY | FILE_FLAG_CREATE, 0644, 1000, 1000, NULL, OBJECT_CREATE_FLAG_INTERNAL, NULL, &file); if (error_code != API_E_SUCCESS) { program_scheduler_handle_error(program_scheduler, false, "Could not open/create '%s' for writing: %s (%d)", program_scheduler->absolute_stderr_file_name->buffer, api_get_error_code_name(error_code), error_code); return NULL; } return file; case PROGRAM_STDIO_REDIRECTION_INDIVIDUAL_LOG: return program_scheduler_prepare_individual_log(program_scheduler, timestamp, "stderr"); case PROGRAM_STDIO_REDIRECTION_CONTINUOUS_LOG: return program_scheduler_prepare_continuous_log(program_scheduler, timestamp, "stderr"); case PROGRAM_STDIO_REDIRECTION_STDOUT: object_add_internal_reference(&stdout->base); return stdout; default: // should never be reachable program_scheduler_handle_error(program_scheduler, true, "Invalid stderr redirection %d", program->config.stderr_redirection); return NULL; } }
APIE program_scheduler_create(ProgramScheduler *program_scheduler, ProgramSchedulerProcessSpawnedFunction process_spawned, ProgramSchedulerStateChangedFunction state_changed, void *opaque) { int phase = 0; Program *program = containerof(program_scheduler, Program, scheduler); APIE error_code; char bin_directory[1024]; char *log_directory; String *dev_null_file_name; int i; String *environment; // format bin directory name if (robust_snprintf(bin_directory, sizeof(bin_directory), "%s/bin", program->root_directory->buffer) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not format program bin directory name: %s (%d)", get_errno_name(errno), errno); goto cleanup; } // create bin directory as default user (UID 1000, GID 1000) error_code = directory_create(bin_directory, DIRECTORY_FLAG_RECURSIVE, 0755, 1000, 1000); if (error_code != API_E_SUCCESS) { goto cleanup; } // format log directory name if (asprintf(&log_directory, "%s/log", program->root_directory->buffer) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not format program log directory name: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 1; // create log directory as default user (UID 1000, GID 1000) error_code = directory_create(log_directory, DIRECTORY_FLAG_RECURSIVE, 0755, 1000, 1000); if (error_code != API_E_SUCCESS) { goto cleanup; } // get '/dev/null' stock string object error_code = inventory_get_stock_string("/dev/null", &dev_null_file_name); if (error_code != API_E_SUCCESS) { goto cleanup; } phase = 2; program_scheduler->process_spawned = process_spawned; program_scheduler->state_changed = state_changed; program_scheduler->opaque = opaque; program_scheduler->absolute_working_directory = NULL; program_scheduler->absolute_stdin_file_name = NULL; program_scheduler->absolute_stdout_file_name = NULL; program_scheduler->absolute_stderr_file_name = NULL; program_scheduler->log_directory = log_directory; program_scheduler->dev_null_file_name = dev_null_file_name; program_scheduler->observer.function = program_scheduler_handle_observer; program_scheduler->observer.opaque = program_scheduler; program_scheduler->observer_state = PROCESS_OBSERVER_STATE_FINISHED; program_scheduler->shutdown = false; program_scheduler->waiting_for_brickd = !network_is_brickd_connected(); program_scheduler->timer_active = false; program_scheduler->cron_active = false; program_scheduler->last_spawned_process = NULL; program_scheduler->last_spawned_timestamp = 0; program_scheduler->state = PROGRAM_SCHEDULER_STATE_STOPPED; program_scheduler->timestamp = time(NULL); program_scheduler->message = NULL; // if X11 is enabled... if (_x11_enabled) { for (i = 0; i < program->config.environment->items.count; ++i) { environment = *(String **)array_get(&program->config.environment->items, i); // ...and the DISPLAY environment variable is set... if (strncmp(environment->buffer, "DISPLAY=", strlen("DISPLAY=")) == 0) { // ...then use the process monitor to wait for lxpanel to start program_scheduler->observer_state = PROCESS_OBSERVER_STATE_PENDING; break; } } } // FIXME: only create timer for interval mode, otherwise this wastes a // file descriptor per non-interval scheduler if (timer_create_(&program_scheduler->timer, program_scheduler_handle_timer, program_scheduler) < 0) { error_code = api_get_error_code_from_errno(); log_error("Could not create timer: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 3; cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 2: string_unlock_and_release(dev_null_file_name); case 1: free(log_directory); default: break; } return phase == 3 ? API_E_SUCCESS : error_code; }