/** * Determine which snapshots in the state queue can be free'd because are placed before the current time barrier. * * Queues are cleaned by deleting all the events the timestamp of which is STRICTLY lower than the time barrier. * Since state_pointer points to an event in queue_in, the state queue must be cleaned after the input queue. * * @author Francesco Quaglia * * @param lid The logical process' local identifier * @param time_barrier The current barrier */ void fossil_collection(unsigned int lid, simtime_t time_barrier) { state_t *state; msg_t *last_kept_event; double committed_events; time_barrier = 0.7 * time_barrier; // State list must be handled differently, as nodes point to malloc'd // nodes. We therefore manually scan the list and free the memory. while( (state = list_head(LPS[lid]->queue_states)) != NULL && state->lvt < time_barrier) { log_delete(list_head(LPS[lid]->queue_states)->log); state->last_event = (void *)0xDEADBABE; list_pop(LPS[lid]->queue_states); } // Determine queue pruning horizon last_kept_event = list_head(LPS[lid]->queue_states)->last_event; // Truncate the input queue, accounting for the event which is pointed by the lastly kept state committed_events = (double)list_trunc_before(LPS[lid]->queue_in, timestamp, last_kept_event->timestamp); statistics_post_lp_data(lid, STAT_COMMITTED, committed_events); // Truncate the output queue list_trunc_before(LPS[lid]->queue_out, send_time, last_kept_event->timestamp); }
int main(int argc, char *argv[]) { (void) argc; (void) argv; struct log *l; l = log_new("/tmp/log_test.txt", LOG_ALL); assert(l); log_clear(l); log_set_level(l, LOG_INFO); log_debug(l, "module-1", "debug message\n"); log_set_level(l, LOG_DEBUG); log_debug(l, "module-1", "debug message\n"); log_info(l, "module-2", "info message\n"); log_warning(l, NULL, "warning message\n"); log_error(l, "module-1","error message\n"); log_printf(l, LOG_WARNING, "module-3", "more warnings - "); log_append(l, "%s\n", "\"this string is appended\""); fprintf(stdout, "log_print():\n"); log_print(l, STDOUT_FILENO); log_delete(l); return 0; }
struct jx * jx_database_remove( struct jx_database *db, const char *key ) { const char *nkey = strdup(key); struct jx *j = hash_table_remove(db->table,key); if(db->logdir && j) { log_delete(db,nkey); log_flush(db); } return j; }
struct nvpair * nvpair_database_remove( struct nvpair_database *db, const char *key ) { const char *nkey = strdup(key); struct nvpair *nv = hash_table_remove(db->table,nkey); if(db->logdir && nv) { log_delete(db,nkey); log_flush(db); } return nv; }
int raft_recv_appendentries( raft_server_t* me_, const int node, msg_appendentries_t* ae) { int i; raft_server_private_t* me = (void*)me_; msg_appendentries_response_t r; me->timeout_elapsed = 0; __log(me_, NULL, "received appendentries from: %d", node); r.term = me->current_term; /* we've found a leader who is legitimate */ if (raft_is_leader(me_) && me->current_term <= ae->term) raft_become_follower(me_); /* 1. Reply false if term < currentTerm (�1) */ if (ae->term < me->current_term) { __log(me_, NULL, "AE term is less than current term"); r.success = 0; goto done; } #if 0 if (-1 != ae->prev_log_idx && ae->prev_log_idx < raft_get_current_idx(me_)) { __log(me_, NULL, "AE prev_idx is less than current idx"); r.success = 0; goto done; } #endif /* not the first appendentries we've received */ if (0 != ae->prev_log_idx) { raft_entry_t* e; if ((e = raft_get_entry_from_idx(me_, ae->prev_log_idx))) { /* 2. Reply false if log doesn抰 contain an entry at prevLogIndex whose term matches prevLogTerm (�3) */ if (e->term != ae->prev_log_term) { __log(me_, NULL, "AE term doesn't match prev_idx"); r.success = 0; goto done; } /* 3. If an existing entry conflicts with a new one (same index but different terms), delete the existing entry and all that follow it (�3) */ raft_entry_t* e2; if ((e2 = raft_get_entry_from_idx(me_, ae->prev_log_idx+1))) { log_delete(me->log, ae->prev_log_idx+1); } } else { __log(me_, NULL, "AE no log at prev_idx"); r.success = 0; goto done; //assert(0); } } /* 5. If leaderCommit > commitIndex, set commitIndex = min(leaderCommit, last log index) */ if (raft_get_commit_idx(me_) < ae->leader_commit) { raft_entry_t* e; if ((e = log_peektail(me->log))) { raft_set_commit_idx(me_, e->id < ae->leader_commit ? e->id : ae->leader_commit); while (1 == raft_apply_entry(me_)); } } if (raft_is_candidate(me_)) raft_become_follower(me_); raft_set_current_term(me_, ae->term); /* append all entries to log */ for (i=0; i<ae->n_entries; i++) { msg_entry_t* cmd; raft_entry_t* c; cmd = &ae->entries[i]; /* TODO: replace malloc with mempoll/arena */ c = malloc(sizeof(raft_entry_t)); c->term = me->current_term; c->len = cmd->len; c->id = cmd->id; c->data = malloc(cmd->len); memcpy(c->data, cmd->data, cmd->len); if (0 == raft_append_entry(me_, c)) { __log(me_, NULL, "AE failure; couldn't append entry"); r.success = 0; goto done; } } r.success = 1; r.current_idx = raft_get_current_idx(me_); r.first_idx = ae->prev_log_idx + 1; done: if (me->cb.send) me->cb.send(me->cb_ctx, me, node, RAFT_MSG_APPENDENTRIES_RESPONSE, (void*)&r, sizeof(msg_appendentries_response_t)); return 1; }
int raft_recv_appendentries( raft_server_t* me_, const int node, msg_appendentries_t* ae, msg_appendentries_response_t *r ) { raft_server_private_t* me = (raft_server_private_t*)me_; me->timeout_elapsed = 0; __log(me_, "received appendentries from: %d", node); r->term = me->current_term; /* we've found a leader who is legitimate */ if (raft_is_leader(me_) && me->current_term <= ae->term) raft_become_follower(me_); /* 1. Reply false if term < currentTerm (§5.1) */ if (ae->term < me->current_term) { __log(me_, "AE term is less than current term"); r->success = 0; return 0; } #if 0 if (-1 != ae->prev_log_idx && ae->prev_log_idx < raft_get_current_idx(me_)) { __log(me_, "AE prev_idx is less than current idx"); r->success = 0; return 0; } #endif /* not the first appendentries we've received */ if (0 != ae->prev_log_idx) { raft_entry_t* e = raft_get_entry_from_idx(me_, ae->prev_log_idx); if (e) { /* 2. Reply false if log doesn't contain an entry at prevLogIndex whose term matches prevLogTerm (§5.3) */ if (e->term != ae->prev_log_term) { __log(me_, "AE term doesn't match prev_idx"); r->success = 0; return 0; } /* 3. If an existing entry conflicts with a new one (same index but different terms), delete the existing entry and all that follow it (§5.3) */ raft_entry_t* e2; e2 = raft_get_entry_from_idx(me_, ae->prev_log_idx + 1); if (e2) log_delete(me->log, ae->prev_log_idx + 1); } else { __log(me_, "AE no log at prev_idx"); r->success = 0; return 0; } } /* 5. If leaderCommit > commitIndex, set commitIndex = min(leaderCommit, last log index) */ if (raft_get_commit_idx(me_) < ae->leader_commit) { raft_entry_t* e = log_peektail(me->log); if (e) { int id = e->id < ae->leader_commit ? e->id : ae->leader_commit; raft_set_commit_idx(me_, id); while (0 == raft_apply_entry(me_)) ; } } if (raft_is_candidate(me_)) raft_become_follower(me_); raft_set_current_term(me_, ae->term); int i; /* append all entries to log */ for (i = 0; i < ae->n_entries; i++) { msg_entry_t* cmd = &ae->entries[i]; /* TODO: replace malloc with mempoll/arena */ raft_entry_t* c = (raft_entry_t*)malloc(sizeof(raft_entry_t)); c->term = me->current_term; c->len = cmd->len; c->id = cmd->id; c->data = (unsigned char*)malloc(cmd->len); memcpy(c->data, cmd->data, cmd->len); if (-1 == raft_append_entry(me_, c)) { __log(me_, "AE failure; couldn't append entry"); r->success = 0; return -1; } } r->success = 1; r->current_idx = raft_get_current_idx(me_); r->first_idx = ae->prev_log_idx + 1; return 0; }
int raft_recv_appendentries( raft_server_t* me_, raft_node_t* node, msg_appendentries_t* ae, msg_appendentries_response_t *r ) { raft_server_private_t* me = (raft_server_private_t*)me_; me->timeout_elapsed = 0; if (0 < ae->n_entries) __log(me_, node, "recvd appendentries from: %lx, t:%d ci:%d lc:%d pli:%d plt:%d #%d", node, ae->term, raft_get_current_idx(me_), ae->leader_commit, ae->prev_log_idx, ae->prev_log_term, ae->n_entries); r->term = me->current_term; if (raft_is_candidate(me_) && me->current_term == ae->term) { me->voted_for = -1; raft_become_follower(me_); } else if (me->current_term < ae->term) { raft_set_current_term(me_, ae->term); r->term = ae->term; raft_become_follower(me_); } else if (ae->term < me->current_term) { /* 1. Reply false if term < currentTerm (§5.1) */ __log(me_, node, "AE term %d is less than current term %d", ae->term, me->current_term); goto fail_with_current_idx; } /* Not the first appendentries we've received */ /* NOTE: the log starts at 1 */ if (0 < ae->prev_log_idx) { raft_entry_t* e = raft_get_entry_from_idx(me_, ae->prev_log_idx); if (!e) { __log(me_, node, "AE no log at prev_idx %d", ae->prev_log_idx); goto fail_with_current_idx; } /* 2. Reply false if log doesn't contain an entry at prevLogIndex whose term matches prevLogTerm (§5.3) */ if (raft_get_current_idx(me_) < ae->prev_log_idx) goto fail_with_current_idx; if (e->term != ae->prev_log_term) { __log(me_, node, "AE term doesn't match prev_term (ie. %d vs %d) ci:%d pli:%d", e->term, ae->prev_log_term, raft_get_current_idx(me_), ae->prev_log_idx); assert(me->commit_idx < ae->prev_log_idx); /* Delete all the following log entries because they don't match */ log_delete(me->log, ae->prev_log_idx); r->current_idx = ae->prev_log_idx - 1; goto fail; } } /* 3. If an existing entry conflicts with a new one (same index but different terms), delete the existing entry and all that follow it (§5.3) */ if (ae->n_entries == 0 && 0 < ae->prev_log_idx && ae->prev_log_idx + 1 < raft_get_current_idx(me_)) { assert(me->commit_idx < ae->prev_log_idx + 1); log_delete(me->log, ae->prev_log_idx + 1); } r->current_idx = ae->prev_log_idx; int i; for (i = 0; i < ae->n_entries; i++) { msg_entry_t* ety = &ae->entries[i]; int ety_index = ae->prev_log_idx + 1 + i; raft_entry_t* existing_ety = raft_get_entry_from_idx(me_, ety_index); r->current_idx = ety_index; if (existing_ety && existing_ety->term != ety->term) { assert(me->commit_idx < ety_index); log_delete(me->log, ety_index); break; } else if (!existing_ety) break; } /* Pick up remainder in case of mismatch or missing entry */ for (; i < ae->n_entries; i++) { int e = raft_append_entry(me_, &ae->entries[i]); if (-1 == e) goto fail_with_current_idx; r->current_idx = ae->prev_log_idx + 1 + i; } /* 4. If leaderCommit > commitIndex, set commitIndex = min(leaderCommit, index of most recent entry) */ if (raft_get_commit_idx(me_) < ae->leader_commit) { int last_log_idx = max(raft_get_current_idx(me_), 1); raft_set_commit_idx(me_, min(last_log_idx, ae->leader_commit)); } /* update current leader because we accepted appendentries from it */ me->current_leader = node; r->success = 1; r->first_idx = ae->prev_log_idx + 1; return 0; fail_with_current_idx: r->current_idx = raft_get_current_idx(me_); fail: r->success = 0; r->first_idx = 0; return -1; }
/* Delete a file or directory. If DEL_RECURSE is set in the flags, this will * delete recursively. * * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's * a directory! (The buffer is used for recursion, but returned unchanged.) */ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) { enum delret ret; char *what; int ok; if (DEBUG_GTE(DEL, 2)) { rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n", fbuf, (int)mode, (int)flags); } if (flags & DEL_NO_UID_WRITE) do_chmod(fbuf, mode | S_IWUSR); if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) { /* This only happens on the first call to delete_item() since * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */ ignore_perishable = 1; /* If DEL_RECURSE is not set, this just reports emptiness. */ ret = delete_dir_contents(fbuf, flags); ignore_perishable = 0; if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT) goto check_ret; /* OK: try to delete the directory. */ } if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && stats.deleted_files >= max_delete) { skipped_deletes++; return DR_AT_LIMIT; } if (S_ISDIR(mode)) { what = "rmdir"; ok = do_rmdir(fbuf) == 0; } else { if (make_backups > 0 && !(flags & DEL_FOR_BACKUP) && (backup_dir || !is_backup_file(fbuf))) { what = "make_backup"; ok = make_backup(fbuf, True); if (ok == 2) { what = "unlink"; ok = robust_unlink(fbuf) == 0; } } else { what = "unlink"; ok = robust_unlink(fbuf) == 0; } } if (ok) { if (!(flags & DEL_MAKE_ROOM)) { log_delete(fbuf, mode); stats.deleted_files++; if (S_ISREG(mode)) { /* Nothing more to count */ } else if (S_ISDIR(mode)) stats.deleted_dirs++; #ifdef SUPPORT_LINKS else if (S_ISLNK(mode)) stats.deleted_symlinks++; #endif else if (IS_DEVICE(mode)) stats.deleted_symlinks++; else stats.deleted_specials++; } ret = DR_SUCCESS; } else { if (S_ISDIR(mode) && errno == ENOTEMPTY) { rprintf(FINFO, "cannot delete non-empty directory: %s\n", fbuf); ret = DR_NOT_EMPTY; } else if (errno != ENOENT) { rsyserr(FERROR, errno, "delete_file: %s(%s) failed", what, fbuf); ret = DR_FAILURE; } else ret = DR_SUCCESS; } check_ret: if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) { const char *desc; switch (flags & DEL_MAKE_ROOM) { case DEL_FOR_FILE: desc = "regular file"; break; case DEL_FOR_DIR: desc = "directory"; break; case DEL_FOR_SYMLINK: desc = "symlink"; break; case DEL_FOR_DEVICE: desc = "device file"; break; case DEL_FOR_SPECIAL: desc = "special file"; break; default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */ } rprintf(FERROR_XFER, "could not make way for %s %s: %s\n", flags & DEL_FOR_BACKUP ? "backup" : "new", desc, fbuf); } return ret; }