/* * perform some basic tests */ static void basic(table_t *tab_p) { long key; int ret; void *data_p; (void)printf("Performing basic tests:\n"); (void)fflush(stdout); key = TEST_VALUE; ret = table_insert(tab_p, &key, sizeof(key), NULL, 0, &data_p, 0); if (ret != TABLE_ERROR_NONE) { (void)fprintf(stderr, "could not store null pointer of size 0 in table: %s\n", table_strerror(ret)); exit(1); } /* try the replace */ ret = table_insert(tab_p, &key, sizeof(key), NULL, 0, &data_p, 1); if (ret != TABLE_ERROR_NONE) { (void)fprintf(stderr, "could not store null pointer of size 0 in table: %s\n", table_strerror(ret)); exit(1); } /* try to insert without replace */ ret = table_insert(tab_p, &key, sizeof(key), NULL, 0, &data_p, 0); if (ret != TABLE_ERROR_OVERWRITE) { (void)printf("replaced a key in the table with no-overwrite flag: %s\n", table_strerror(ret)); exit(1); } /* delete the key */ ret = table_delete(tab_p, &key, sizeof(key), NULL, NULL); if (ret != TABLE_ERROR_NONE) { (void)fprintf(stderr, "could not delete test key %ld: %s\n", key, table_strerror(ret)); exit(1); } /* test to make sure we can insert a NULL with size > 0 */ ret = table_insert(tab_p, &key, sizeof(key), NULL, 100, &data_p, 0); if (ret != TABLE_ERROR_NONE) { (void)printf("could not add NULL with size > 0: %s\n", table_strerror(ret)); exit(1); } ret = table_delete(tab_p, &key, sizeof(key), NULL, NULL); if (ret != TABLE_ERROR_NONE) { (void)fprintf(stderr, "could not delete test key %ld: %s\n", key, table_strerror(ret)); exit(1); } }
void table_main(int ac, char **av) { if (!strncmp(*av, "append", strlen(*av))) { table_append(ac, av); } else if (!strncmp(*av, "remove", strlen(*av))) { table_remove(ac, av); } else if (!strncmp(*av, "flush", strlen(*av))) { table_flush(ac, av); } else if (!strncmp(*av, "list", strlen(*av))) { table_list(ac, av); } else if (!strncmp(*av, "show", strlen(*av))) { table_show(ac, av); } else if (!strncmp(*av, "type", strlen(*av))) { table_create(ac, av); } else if (!strncmp(*av, "delete", strlen(*av))) { table_delete(ac, av); } else if (!strncmp(*av, "test", strlen(*av))) { table_test(ac,av); } else if (!strncmp(*av, "name", strlen(*av))) { table_rename(ac, av); } else { errx(EX_USAGE, "bad ipfw table command `%s'", *av); } }
class_type make_class(class_type c, list_type resources, list_type classvars, list_type properties, list_type messages) { int has_constructor = False; c->resources = resources; c->classvars = list_append(st.override_classvars, classvars); c->properties = properties; /* Sort message handlers by id # */ c->messages = SortMessageHandlerList(messages); /* Save away total # of properties in this class + parents */ c->numproperties = st.maxproperties; /* Save away total # of class variables in this class + parents */ c->numclassvars = st.maxclassvars + 1; /* Clean out class variable table */ table_delete(st.classvars); st.override_classvars = NULL; /* Erase constant list */ st.constants = list_delete(st.constants); st.maxproperties = 0; // Property #0 is reserved for SELF st.maxclassvars = -1; return c; }
message_handler_type make_message_handler(message_header_type header, char *comment, list_type locals, list_type stmts) { message_handler_type h = (message_handler_type) SafeMalloc(sizeof(message_handler_struct)); stmt_type stmt; /* Last statement of body must be PROPAGATE or RETURN */ stmt = (stmt_type) list_last_item(stmts); if (stmt == NULL || (stmt->type != S_RETURN && stmt->type != S_PROP)) action_error("Last statement must be PROPAGATE or RETURN"); h->header = header; h->locals = locals; h->body = stmts; if (comment == NULL) h->comment = NULL; else h->comment = make_string_constant(comment); /* Clean out local variable table. We must do this at the end of * each handler, since in make_message_header we have already checked * parameters names against old variables, which includes parameters * from the current function in the local table. */ table_delete(st.localvars); st.maxlocals = -1; /* So that first local is numbered 0 */ return h; }
void ssl_scache_shmht_expire(server_rec *s) { SSLModConfigRec *mc = myModConfig(); SSLSrvConfigRec *sc = mySrvConfig(s); static time_t tLast = 0; table_linear_t iterator; time_t tExpiresAt; void *vpKey; void *vpKeyThis; void *vpData; int nKey; int nKeyThis; int nData; int nElements = 0; int nDeleted = 0; int bDelete; int rc; time_t tNow; /* * make sure the expiration for still not-accessed session * cache entries is done only from time to time */ tNow = time(NULL); if (tNow < tLast+sc->nSessionCacheTimeout) return; tLast = tNow; ssl_mutex_on(s); if (table_first_r(mc->tSessionCacheDataTable, &iterator, &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE) { do { bDelete = FALSE; nElements++; if (nData < sizeof(time_t) || vpData == NULL) bDelete = TRUE; else { memcpy(&tExpiresAt, vpData, sizeof(time_t)); if (tExpiresAt <= tNow) bDelete = TRUE; } vpKeyThis = vpKey; nKeyThis = nKey; rc = table_next_r(mc->tSessionCacheDataTable, &iterator, &vpKey, &nKey, &vpData, &nData); if (bDelete) { table_delete(mc->tSessionCacheDataTable, vpKeyThis, nKeyThis, NULL, NULL); nDeleted++; } } while (rc == TABLE_ERROR_NONE); } ssl_mutex_off(s); ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache (SHMHT) Expiry: " "old: %d, new: %d, removed: %d", nElements, nElements-nDeleted, nDeleted); return; }
void close_inotify() { if (watches != NULL) { table_delete(watches); } if (inotify_fd >= 0) { close(inotify_fd); } }
void ssl_scache_shmht_remove(server_rec *s, UCHAR *id, int idlen) { SSLModConfigRec *mc = myModConfig(); /* remove value under key in table */ ssl_mutex_on(s); table_delete(mc->tSessionCacheDataTable, id, idlen, NULL, NULL); ssl_mutex_off(s); return; }
/* bool delete_table(id, table_name) */ static int cc_delete_table(lua_State* L) { int id; bool retcode; const char* table_name; database_handler_t* database_handler; worker_handler_t* handler = find_handler_by_stack(L); int args = lua_gettop(L); if (args < 2) { error_log("`%s` parameter lack:%d\n", __FUNCTION__, args); return 0; } if (!lua_isnumber(L, -args)) { error_log("`%s` parameter error:%s\n", __FUNCTION__, lua_typename(L, lua_type(L, -args))); return 0; } if (!lua_isstring(L, -(args-1))) { error_log("`%s` parameter error:%s\n", __FUNCTION__, lua_typename(L, lua_type(L, -(args-1)))); return 0; } id = lua_tointeger(L, -args); table_name = lua_tostring(L, -(args-1)); database_handler = hash_table_find(handler->database_table, id); if (!database_handler) { error_log("`%s` not found database:%d\n", __FUNCTION__, id); return 0; } retcode = table_delete(database_handler, table_name); lua_pushboolean(L, retcode ? 1 : 0); return 1; }
static CTL_MSG * lookup_request (CTL_MSG * request, int (*comp) (table_t *, CTL_MSG *, time_t *)) { table_t *ptr; time_t now; time (&now); if (debug) print_request ("lookup_request", request); for (ptr = table; ptr; ptr = ptr->next) { if (debug) print_request ("comparing against: ", &ptr->request); if ((ptr->time - now) > max_request_ttl) { /* the entry is too old */ if (debug) print_request ("deleting expired entry", &ptr->request); table_delete (ptr); } else { if (comp (ptr, request, &now) == 0) { if (debug) print_request ("found", &ptr->request); return &ptr->request; } } } if (debug) syslog (LOG_DEBUG, "not found"); return NULL; }
/* * simple_table_delete - delete a tuple * * This routine may be used to delete a tuple when concurrent updates of * the target tuple are not expected (for example, because we have a lock * on the relation associated with the tuple). Any failure is reported * via ereport(). */ void simple_table_delete(Relation rel, ItemPointer tid, Snapshot snapshot) { TM_Result result; TM_FailureData tmfd; result = table_delete(rel, tid, GetCurrentCommandId(true), snapshot, InvalidSnapshot, true /* wait for commit */ , &tmfd, false /* changingPart */ ); switch (result) { case TM_SelfModified: /* Tuple was already updated in current command? */ elog(ERROR, "tuple already updated by self"); break; case TM_Ok: /* done successfully */ break; case TM_Updated: elog(ERROR, "tuple concurrently updated"); break; case TM_Deleted: elog(ERROR, "tuple concurrently deleted"); break; default: elog(ERROR, "unrecognized table_delete status: %u", result); break; } }
/* * try ITERN random program iterations. */ static void stress(table_t *tab_p, const int iter_n, const int mmaping_b) { void *data, *key; int which = 0, mode, weight_total; int iter_c, pnt_c, free_c, ret, ksize, dsize; entry_t *grid, *free_p, *grid_p, *last_p; int linear_b = 0, linear_eof_b = 0; (void)printf("Performing stress tests with %d iterations:\n", iter_n); (void)fflush(stdout); grid = malloc(sizeof(entry_t) * MAX_ENTRIES); if (grid == NULL) { (void)printf("problems allocating space for %d entries.\n", MAX_ENTRIES); exit(1); } /* initialize free list */ free_p = grid; for (grid_p = grid; grid_p < grid + MAX_ENTRIES; grid_p++) { grid_p->en_free_b = 1; grid_p->en_key = NULL; grid_p->en_key_size = 0; grid_p->en_data = NULL; grid_p->en_data_size = 0; grid_p->en_next_p = grid_p + 1; } /* redo the last next pointer */ (grid_p - 1)->en_next_p = NULL; free_c = MAX_ENTRIES; #if 0 /* load the list */ if (mmaping_b) { for (ret = table_first(tab_p, (void **)&key_p, NULL, (void **)&data_p, NULL); ret == TABLE_ERROR_NONE; ret = table_next(tab_p, (void **)&key_p, NULL, (void **)&data_p, NULL)) { } } #endif /* total the weights */ weight_total = 0; for (mode = 0; mode < MODE_MAX; mode++) { weight_total += mode_weights[mode]; } for (iter_c = 0; iter_c < iter_n;) { int weight; /* decide what to do */ weight = RANDOM_VALUE(weight_total) + 1; for (mode = 0; mode < MODE_MAX; mode++) { weight -= mode_weights[mode]; if (weight <= 0) { break; } } /* out of bounds */ if (mode >= MODE_MAX) { continue; } switch (mode) { case MODE_CLEAR: if (mmaping_b || large_b) { continue; } call_c++; table_clear(tab_p); /* re-init free list */ free_p = grid; for (grid_p = grid; grid_p < grid + MAX_ENTRIES; grid_p++) { if (! grid_p->en_free_b) { if (grid_p->en_key != NULL) { free(grid_p->en_key); } if (grid_p->en_data != NULL) { free(grid_p->en_data); } } grid_p->en_free_b = 1; grid_p->en_next_p = grid_p + 1; } /* redo the last next pointer */ (grid_p - 1)->en_next_p = NULL; free_c = MAX_ENTRIES; linear_b = 0; linear_eof_b = 0; iter_c++; if (verbose_b) { (void)printf("table cleared.\n"); fflush(stdout); } break; case MODE_INSERT: if (mmaping_b) { continue; } if (free_c > 0) { which = RANDOM_VALUE(free_c); last_p = NULL; grid_p = free_p; for (pnt_c = 0; pnt_c < which && grid_p != NULL; pnt_c++) { last_p = grid_p; grid_p = grid_p->en_next_p; } if (grid_p == NULL) { (void)printf("reached end of free list prematurely\n"); exit(1); } do { key = random_block(&ksize); } while (key == NULL); data = random_block(&dsize); call_c++; ret = table_insert(tab_p, key, ksize, data, dsize, NULL, 0); if (ret == TABLE_ERROR_NONE) { if (verbose_b) { (void)printf("stored in pos %d: %d, %d bytes of key, data\n", grid_p - grid, ksize, dsize); fflush(stdout); } grid_p->en_free_b = 0; grid_p->en_key = key; grid_p->en_key_size = ksize; grid_p->en_data = data; grid_p->en_data_size = dsize; /* shift free list */ if (last_p == NULL) { free_p = grid_p->en_next_p; } else { last_p->en_next_p = grid_p->en_next_p; } grid_p->en_next_p = NULL; free_c--; iter_c++; } else { for (grid_p = grid; grid_p < grid + MAX_ENTRIES; grid_p++) { if (grid_p->en_free_b) { continue; } if (grid_p->en_key_size == ksize && memcmp(grid_p->en_key, key, ksize) == 0) { break; } } /* if we did not store it then error */ if (grid_p >= grid + MAX_ENTRIES) { (void)fprintf(stderr, "ERROR storing #%d: %s\n", which, table_strerror(ret)); } if (key != NULL) { free(key); } if (data != NULL) { free(data); } } } break; case MODE_OVERWRITE: if (mmaping_b) { continue; } if (free_c < MAX_ENTRIES) { which = RANDOM_VALUE(MAX_ENTRIES); if (grid[which].en_free_b) { continue; } data = random_block(&dsize); call_c++; ret = table_insert(tab_p, grid[which].en_key, grid[which].en_key_size, data, dsize, NULL, 1); if (ret == TABLE_ERROR_NONE) { if (verbose_b) { (void)printf("overwrite pos %d with data of %d bytes\n", which, dsize); fflush(stdout); } grid[which].en_free_b = 0; if (grid[which].en_data != NULL) { free(grid[which].en_data); } grid[which].en_data = data; grid[which].en_data_size = dsize; grid[which].en_next_p = NULL; free_c--; iter_c++; } else { (void)fprintf(stderr, "ERROR overwriting #%d: %s\n", which, table_strerror(ret)); free(data); } } break; case MODE_RETRIEVE: if (free_c < MAX_ENTRIES) { which = RANDOM_VALUE(MAX_ENTRIES); if (grid[which].en_free_b) { continue; } call_c++; ret = table_retrieve(tab_p, grid[which].en_key, grid[which].en_key_size, (void **)&data, &dsize); if (ret == TABLE_ERROR_NONE) { if (grid[which].en_data_size == dsize && memcmp(grid[which].en_data, data, dsize) == 0) { if (verbose_b) { (void)printf("retrieved key #%d, got data of %d bytes\n", which, dsize); fflush(stdout); } } else { (void)fprintf(stderr, "ERROR: retrieve key #%d: data (%d bytes) didn't " "match table (%d bytes)\n", which, grid[which].en_data_size, dsize); } iter_c++; } else { (void)fprintf(stderr, "error retrieving key #%d: %s\n", which, table_strerror(ret)); } } break; case MODE_DELETE: if (mmaping_b) { continue; } if (free_c >= MAX_ENTRIES) { continue; } which = RANDOM_VALUE(MAX_ENTRIES); if (grid[which].en_free_b) { continue; } call_c++; ret = table_delete(tab_p, grid[which].en_key, grid[which].en_key_size, (void **)&data, &dsize); if (ret == TABLE_ERROR_NONE) { if (grid[which].en_data_size == dsize && memcmp(grid[which].en_data, data, dsize) == 0) { if (verbose_b) { (void)printf("deleted key #%d, got data of %d bytes\n", which, dsize); fflush(stdout); } } else { (void)fprintf(stderr, "ERROR deleting key #%d: data didn't match table\n", which); } grid[which].en_free_b = 1; if (grid[which].en_key != NULL) { free(grid[which].en_key); } if (grid[which].en_data != NULL) { free(grid[which].en_data); } grid[which].en_next_p = free_p; free_p = grid + which; free_c++; if (free_c == MAX_ENTRIES) { linear_b = 0; linear_eof_b = 0; } iter_c++; if (data != NULL) { free(data); } } else { (void)fprintf(stderr, "ERROR deleting key %d: %s\n", which, table_strerror(ret)); } break; case MODE_DELETE_FIRST: /* * We have a problem here. This is the only action routine * which modifies the table and is not key based. We don't have * a way of looking up the key in our local data structure. */ break; case MODE_FIRST: call_c++; ret = table_first(tab_p, (void **)&key, &ksize, (void **)&data, &dsize); if (ret == TABLE_ERROR_NONE) { linear_b = 1; linear_eof_b = 0; if (verbose_b) { (void)printf("first entry has key, data of %d, %d bytes\n", ksize, dsize); fflush(stdout); } iter_c++; } else if (free_c == MAX_ENTRIES) { if (verbose_b) { (void)printf("no first in table\n"); fflush(stdout); } } else { (void)fprintf(stderr, "ERROR: first in table: %s\n", table_strerror(ret)); } break; case MODE_NEXT: call_c++; ret = table_next(tab_p, (void **)&key, &ksize, (void **)&data, &dsize); if (ret == TABLE_ERROR_NONE) { if (verbose_b) { (void)printf("next entry has key, data of %d, %d\n", ksize, dsize); fflush(stdout); } iter_c++; } else if (ret == TABLE_ERROR_LINEAR && (! linear_b)) { if (verbose_b) { (void)printf("no first command run yet\n"); fflush(stdout); } } else if (ret == TABLE_ERROR_NOT_FOUND) { if (verbose_b) { (void)printf("reached EOF with next in table: %s\n", table_strerror(ret)); fflush(stdout); } linear_b = 0; linear_eof_b = 1; } else { (void)fprintf(stderr, "ERROR: table_next reports: %s\n", table_strerror(ret)); linear_b = 0; linear_eof_b = 0; } break; case MODE_THIS: call_c++; ret = table_this(tab_p, (void **)&key, &ksize, (void **)&data, &dsize); if (ret == TABLE_ERROR_NONE) { if (verbose_b) { (void)printf("this entry has key,data of %d, %d bytes\n", ksize, dsize); fflush(stdout); } iter_c++; } else if (ret == TABLE_ERROR_LINEAR && (! linear_b)) { if (verbose_b) { (void)printf("no first command run yet\n"); fflush(stdout); } } else if (ret == TABLE_ERROR_NOT_FOUND || linear_eof_b) { if (verbose_b) { (void)printf("table linear already reached EOF\n"); fflush(stdout); } } else { (void)fprintf(stderr, "ERROR: this table: %s\n", table_strerror(ret)); linear_b = 0; linear_eof_b = 0; } break; case MODE_INFO: { int buckets, entries; call_c++; ret = table_info(tab_p, &buckets, &entries); if (ret == TABLE_ERROR_NONE) { if (verbose_b) { (void)printf("table has %d buckets, %d entries\n", buckets, entries); fflush(stdout); } iter_c++; } else { (void)fprintf(stderr, "ERROR: table info: %s\n", table_strerror(ret)); } } break; case MODE_ADJUST: { int buckets, entries; if (mmaping_b || auto_adjust_b || large_b) { continue; } call_c++; ret = table_info(tab_p, &buckets, &entries); if (ret == TABLE_ERROR_NONE) { if (entries == 0) { if (verbose_b) { (void)printf("cannot adjusted table, %d entries\n", entries); fflush(stdout); } } else if (buckets == entries) { if (verbose_b) { (void)printf("no need to adjust table, %d buckets and entries\n", buckets); fflush(stdout); } } else { ret = table_adjust(tab_p, entries); if (ret == TABLE_ERROR_NONE) { (void)printf("adjusted table from %d to %d buckets\n", buckets, entries); iter_c++; } else { (void)printf("ERROR: table adjust to %d buckets: %s\n", entries, table_strerror(ret)); } } } else { (void)fprintf(stderr, "ERROR: table info: %s\n", table_strerror(ret)); } } break; default: (void)printf("unknown mode %d\n", which); break; } } /* run through the grid and free the entries */ for (grid_p = grid; grid_p < grid + MAX_ENTRIES; grid_p++) { if (! grid_p->en_free_b) { if (grid_p->en_key != NULL) { free(grid_p->en_key); } if (grid_p->en_data != NULL) { free(grid_p->en_data); } } } /* free used pointers */ free(grid); }
mysql::Binary_log_event *process_event(mysql::Binary_log_event *event) { if (event->get_event_type() != mysql::USER_DEFINED) return event; std::cout << "Replay: Event type: [" << mysql::system::get_event_type_str(event->get_event_type()) << "] length: " << event->header()->event_length << " next pos: " << event->header()->next_position << std::endl; mysql::Transaction_log_event *trans = static_cast<mysql::Transaction_log_event *>(event); int row_count = 0; /* The transaction event we created has aggregated all row events in an ordered list. */ std::list<Binary_log_event *>::iterator it = (trans->m_events).begin(); mysql::Binary_log_event *event1; for (; it != (trans->m_events).end(); ++it) { event1 = *it; std::cout << "transaction log event!! [" << event->get_event_type() << "], binlogev_type [" << event1->get_event_type() << "]\n"; switch (event1->get_event_type()) { case mysql::WRITE_ROWS_EVENT: case mysql::WRITE_ROWS_EVENT_V1: case mysql::DELETE_ROWS_EVENT: case mysql::DELETE_ROWS_EVENT_V1: case mysql::UPDATE_ROWS_EVENT: case mysql::UPDATE_ROWS_EVENT_V1: std::cout << "transaction log event[write/delete/update]!!\n"; mysql::Row_event *rev = static_cast<mysql::Row_event *>(event1); uint64_t table_id = rev->table_id; Int_to_Event_map::iterator tm_it = trans->table_map().find(table_id); if (tm_it != trans->table_map().end()) { std::cout << "transaction log event!![TABLE_ID FOUND]\n"; Binary_log_event *tmevent = tm_it->second; assert(tmevent != NULL); mysql::Table_map_event *tm = static_cast<mysql::Table_map_event *>(tmevent); /* Each row event contains multiple rows and fields. The Row_iterator allows us to iterate one row at a time. */ mysql::Row_event_set rows(rev, tm); /* Create a fully qualified table name */ std::ostringstream os; os << tm->db_name << '.' << tm->table_name; std::cout << "transaction log event!![TABLE is " << os.str() << "]\n"; try { mysql::Row_event_set::iterator it = rows.begin(); std::cout << "transaction log event!![after rows.begin]\n"; do { mysql::Row_of_fields fields = *it; if (event1->get_event_type() == mysql::WRITE_ROWS_EVENT || event1->get_event_type() == mysql::WRITE_ROWS_EVENT_V1) { std::cout << "transaction log event!![WRITE]\n"; table_insert(os.str(), fields); } if (event1->get_event_type() == mysql::UPDATE_ROWS_EVENT || event1->get_event_type() == mysql::UPDATE_ROWS_EVENT_V1) { ++it; mysql::Row_of_fields fields2 = *it; std::cout << "transaction log event!![UPDATE]\n"; table_update(os.str(), fields, fields2); } if (event1->get_event_type() == mysql::DELETE_ROWS_EVENT || event1->get_event_type() == mysql::DELETE_ROWS_EVENT_V1) { std::cout << "transaction log event!![DELETE]\n"; table_delete(os.str(), fields); } } while (++it != rows.end()); } catch (const std::logic_error &le) { std::cout << "MySQL Data Type error: " << le.what() << '\n'; } catch (std::exception const& ex) { std::cout << "transaction log event error: " << ex.what() << "\n"; } } else { std::cout << "Table id " << table_id << " was not registered by any preceding table map event." << std::endl; continue; } } } /* Consume the event */ delete trans; return 0; }
int main (int argc, char **argv) { Table *tab; int ii, jj; Alignment *sol; int nsol = 1; int done; if (argc < 3) errx (EXIT_FAILURE, "please provide two strings on the command line, for example 'vbr yog'"); tab = table_new (argv[1], argv[2]); printf ("input source: %s\n" "input destination: %s\n", argv[1], argv[2]); /*************************************************** * propagate */ for (ii = 1; ii <= tab->srclen; ++ii) { for (jj = 1; jj <= tab->dstlen; ++jj) { int best; char * act; tab->state[ii][jj].v_ins = tab->state[ii][jj-1].v_best + GAP_COST; best = tab->state[ii][jj].v_ins; tab->state[ii][jj].v_del = tab->state[ii-1][jj].v_best + GAP_COST; if (best < tab->state[ii][jj].v_del) best = tab->state[ii][jj].v_del; tab->state[ii][jj].v_match = tab->state[ii-1][jj-1].v_best + match_cost (tab->src[ii-1], /* use ii-1 because of the extra "gap" at the beginning */ tab->dst[jj-1]); if (best < tab->state[ii][jj].v_match) best = tab->state[ii][jj].v_match; act = tab->state[ii][jj].act; if (best == tab->state[ii][jj].v_match) *(act++) = 'm'; if (best == tab->state[ii][jj].v_del) *(act++) = 'd'; if (best == tab->state[ii][jj].v_ins) *(act++) = 'i'; *(act++) = '\0'; tab->state[ii][jj].v_best = best; } } /*************************************************** * print */ printf ("\n _"); for (ii = 1; ii <= tab->dstlen; ++ii) printf (" %c", tab->dst[ii-1]); printf ("\n\n"); for (ii = 0; ii <= tab->srclen; ++ii) { printf ("%c", ii == 0 ? '_' : tab->src[ii-1]); for (jj = 0; jj <= tab->dstlen; ++jj) printf (" % 4d", tab->state[ii][jj].v_best); printf ("\n "); for (jj = 0; jj <= tab->dstlen; ++jj) printf (" %4s", tab->state[ii][jj].act); printf ("\n\n"); } /*************************************************** * trace back */ sol = alignment_new (tab); for (done = 0; done != 1; /**/) { int ncheck; done = 1; /* check for branches, but may end up appending duplicates which should not be checked this time around... so remember the old size in ncheck */ ncheck = nsol; for (ii = 0; ii < ncheck; ++ii) { /* skip finished alignments */ if (sol[ii].isrc == 0 && sol[ii].idst == 0) continue; /* check whether we have a 2nd and a 3rd action */ for (jj = 1; jj <= 2; ++jj) { /* no more actions when we hit the '\0' of the action string */ if (tab->state[sol[ii].isrc][sol[ii].idst].act[jj] == '\0') break; /* append a duplicate of sol[ii] that uses jj as iact */ if (NULL == (sol = realloc (sol, (nsol + 1) * sizeof *sol))) err (EXIT_FAILURE, "realloc sol"); alignment_dup (sol + nsol, sol + ii, jj); ++nsol; } } /* update all alignment branches */ for (ii = 0; ii < nsol; ++ii) { char act; /* skip finished alignments */ if (sol[ii].isrc == 0 && sol[ii].idst == 0) continue; /* perform next action in the backtrace */ done = 0; act = tab->state[sol[ii].isrc][sol[ii].idst].act[sol[ii].iact]; if ('m' == act) { *(--sol[ii].src) = tab->src[--sol[ii].isrc]; *(--sol[ii].dst) = tab->dst[--sol[ii].idst]; } else if ('i' == act) { *(--sol[ii].src) = '_'; *(--sol[ii].dst) = tab->dst[--sol[ii].idst]; } else if ('d' == act) { *(--sol[ii].src) = tab->src[--sol[ii].isrc]; *(--sol[ii].dst) = '_'; } else errx (EXIT_FAILURE, "BUG: action %d solution %d isrc %d idst %d iact %d", (int) act, ii, sol[ii].isrc, sol[ii].idst, sol[ii].iact); /* reset iact to zero (only becomes non-zero in the branch detection) */ sol[ii].iact = 0; } } /* print all optimal alignments */ printf ("backtrace:\n\n"); for (ii = 0; ii < nsol; ++ii) printf ("output source: %s\n" "output destination: %s\n\n", sol[ii].src, sol[ii].dst); /*************************************************** * clean up after ourselves */ for (ii = 0; ii < nsol; ++ii) { free (sol[ii].srcbuf); free (sol[ii].dstbuf); } free (sol); table_delete (tab); return 0; }
int main (int argc, char **argv) { Table *tab; int ii, jj; if (argc < 3) errx (EXIT_FAILURE, "please provide two strings on the command line"); tab = table_new (argv[1], argv[2]); printf ("input source: %s\n" "input destination: %s\n", argv[1], argv[2]); /*************************************************** * propagate */ for (ii = 1; ii <= tab->srclen; ++ii) { for (jj = 1; jj <= tab->dstlen; ++jj) { int best; char * act; tab->state[ii][jj].v_ins = tab->state[ii][jj-1].v_best + GAP_COST; best = tab->state[ii][jj].v_ins; tab->state[ii][jj].v_del = tab->state[ii-1][jj].v_best + GAP_COST; if (best < tab->state[ii][jj].v_del) best = tab->state[ii][jj].v_del; tab->state[ii][jj].v_match = tab->state[ii-1][jj-1].v_best + match_cost (tab->src[ii-1], /* use ii-1 because of the extra "gap" at the beginning */ tab->dst[jj-1]); if (best < tab->state[ii][jj].v_match) best = tab->state[ii][jj].v_match; if (best < 0) best = 0; act = tab->state[ii][jj].act; if (best == tab->state[ii][jj].v_match) *(act++) = 'm'; if (best == tab->state[ii][jj].v_del) *(act++) = 'd'; if (best == tab->state[ii][jj].v_ins) *(act++) = 'i'; *(act++) = '\0'; tab->state[ii][jj].v_best = best; } } /*************************************************** * print */ printf ("\n _"); for (ii = 1; ii <= tab->dstlen; ++ii) printf (" %c", tab->dst[ii-1]); printf ("\n\n"); for (ii = 0; ii <= tab->srclen; ++ii) { printf ("%c", ii == 0 ? '_' : tab->src[ii-1]); for (jj = 0; jj <= tab->dstlen; ++jj) printf (" % 4d", tab->state[ii][jj].v_best); printf ("\n "); for (jj = 0; jj <= tab->dstlen; ++jj) printf (" %4s", tab->state[ii][jj].act); printf ("\n\n"); } /*************************************************** * trace back is not so easy with Smith-Waterman, will skip it for * now */ /*************************************************** * clean up after ourselves */ table_delete (tab); return 0; }
/* driver to test sequence of inserts and deletes. */ void equilibriumDriver(void) { int i, code; int key_range, num_keys; int size; int ran_index; int suc_search, suc_trials, unsuc_search, unsuc_trials; int keys_added, keys_removed; int *ip; table_t *test_table; hashkey_t key; data_t dp; clock_t start, end; /* print parameters for this test run */ printf("\n----- Equilibrium test driver -----\n"); printf(" Trials: %d\n", Trials); test_table = table_construct(TableSize, ProbeDec); num_keys = (int) (TableSize * LoadFactor); /* build a table as starting point */ build_table(test_table, num_keys); size = num_keys; key_range = MAXID - MINID + 1; /* in equilibrium make inserts and removes with equal probability */ suc_search = suc_trials = unsuc_search = unsuc_trials = 0; keys_added = keys_removed = 0; start = clock(); for (i = 0; i < Trials; i++) { if (drand48() < 0.5 && table_full(test_table) == FALSE) { // insert only if table not full // for separate chaining table is never full key = (hashkey_t) (drand48() * key_range) + MINID; ip = (int *) malloc(sizeof(int)); *ip = key; /* insert returns 0 if key not found, 1 if older key found */ if (Verbose) printf("Trial %d, Insert Key %u", i, key); code = table_insert(test_table, key, ip); if (code == 0) { /* key was not in table so added */ unsuc_search += table_stats(test_table); unsuc_trials++; keys_added++; if (Verbose) printf(" added\n"); } else if (code == 1) { suc_search += table_stats(test_table); suc_trials++; if (Verbose) printf(" replaced (rare!)\n"); } else { printf("!!!Trial %d failed to insert key (%u) with code (%d)\n", i, key, code); exit(10); } } else if (table_entries(test_table) > TableSize/4) { // delete only if table is at least 25% full // why 25%? Would 10% be better? Lower than 10% will // be computationally expensive do { ran_index = (int) (drand48() * TableSize); key = table_peek(test_table, ran_index,0); } while (key == 0); if (Verbose) printf("Trial %d, Delete Key %u", i, key); if (key < MINID || MAXID < key) { printf("\n\n table peek failed: invalid key (%u) during trial (%d)\n", key, i); exit(12); } dp = table_delete(test_table, key); if (dp != NULL) { if (Verbose) printf(" removed\n"); suc_search += table_stats(test_table); suc_trials++; keys_removed++; assert(*(int *)dp == key); free(dp); } else { printf("!!! failed to find key (%u) in table, trial (%d)!\n", key, i); printf("this is a catastrophic error!!!\n"); exit(11); } } } end = clock(); if (Verbose) { printf("Table after equilibrium trials\n"); table_debug_print(test_table); } size += keys_added - keys_removed; printf(" Keys added (%d), removed (%d) new size should be (%d) and is (%d)\n", keys_added, keys_removed, size, table_entries(test_table)); assert(size == table_entries(test_table)); printf(" After exercise, time=%g \n", 1000*((double)(end-start))/CLOCKS_PER_SEC); printf(" successful searches during exercise=%g, trials=%d\n", (double) suc_search/suc_trials, suc_trials); printf(" unsuccessful searches during exercise=%g, trials=%d\n", (double) unsuc_search/unsuc_trials, unsuc_trials); /* test access times for new table */ /* separate chaining handled differently * should improve design of table_peek function so it * returns 0 if count is invalid when using open addressing. * In current design it is ignored */ suc_search = suc_trials = unsuc_search = unsuc_trials = 0; start = clock(); /* check each position in table for key */ if (ProbeDec == CHAIN) { for (i = 0; i < TableSize; i++) { int count = 0; key = table_peek(test_table, i, count); while (key != 0) { assert(MINID <= key && key <= MAXID); dp = table_retrieve(test_table, key); if (dp == NULL) { printf("Failed key (%u) should be at (%d)\n", key, i); exit(15); } else { suc_search += table_stats(test_table); suc_trials++; assert(*(int *)dp == key); } key = table_peek(test_table, i, ++count); } } } else { for (i = 0; i < TableSize; i++) { key = table_peek(test_table, i, 0); if (key != 0) { assert(MINID <= key && key <= MAXID); dp = table_retrieve(test_table, key); if (dp == NULL) { printf("Failed to find key (%u) but it is in location (%d)\n", key, i); exit(16); } else { suc_search += table_stats(test_table); suc_trials++; assert(*(int *)dp == key); } } } } for (i = 0; i < Trials; i++) { /* random key with uniform distribution */ key = (hashkey_t) (drand48() * key_range) + MINID; dp = table_retrieve(test_table, key); if (dp == NULL) { unsuc_search += table_stats(test_table); unsuc_trials++; } else { // this should be very rare assert(*(int *)dp == key); } } end = clock(); size = table_entries(test_table); printf(" After retrieve experiment, time=%g\n", 1000*((double)(end-start))/CLOCKS_PER_SEC); printf(" New load factor = %g\n", (double) size/TableSize); printf(" Percent empty locations marked deleted = %g\n", (double) 100.0 * table_deletekeys(test_table) / (TableSize - table_entries(test_table))); printf(" Measured avg probes for successful search=%g, trials=%d\n", (double) suc_search/suc_trials, suc_trials); if (ProbeDec == CHAIN && LoadFactor > 0.5 && LoadFactor < 1.5) { printf(" ** This measure is biased. See comments\n\n"); /* The design of the equilibirum driver depends on the uniform * selection of keys to insert and remove. For linear, double, and * quadratic probing selecting a key to remove is done with a uniform * distribution among all possible keys. However, for separate * chaining, the algorithm simply picks a table location with a uniform * distribution, but this is not the same as picking a key with a * uniform distribution. So, there is a bias that a key in a table * location with fewer other keys is more likely to be selected. This * causes the average number of probes for a successful search to * increase as the equilibrium driver runs for a long time. To remove * the bias, a solution is needed to pick a key with a uniform * distribution when chaining is used. It is not clear how to select a * key with low computational cost. */ } printf(" Measured avg probes for unsuccessful search=%g, trials=%d\n", (double) unsuc_search/unsuc_trials, unsuc_trials); printf(" Do deletions increase avg number of probes?\n"); performanceFormulas((double) size/TableSize); /* rehash and retest table */ printf(" Rehash table\n"); test_table = table_rehash(test_table, TableSize); /* number entries in table should not change */ assert(size == table_entries(test_table)); /* rehashing must clear all entries marked for deletion */ assert(0 == table_deletekeys(test_table)); /* test access times for rehashed table */ suc_search = suc_trials = unsuc_search = unsuc_trials = 0; start = clock(); /* check each position in table for key */ if (ProbeDec == CHAIN) { for (i = 0; i < TableSize; i++) { int count = 0; key = table_peek(test_table, i, count); while (key != 0) { assert(MINID <= key && key <= MAXID); dp = table_retrieve(test_table, key); if (dp == NULL) { printf("Failed key (%u) should be at (%d)\n", key, i); exit(25); } else { suc_search += table_stats(test_table); suc_trials++; assert(*(int *)dp == key); } key = table_peek(test_table, i, ++count); } } } else { for (i = 0; i < TableSize; i++) { key = table_peek(test_table, i, 0); if (key != 0) { assert(MINID <= key && key <= MAXID); dp = table_retrieve(test_table, key); if (dp == NULL) { printf("Failed to find key (%u) after rehash but it is in location (%d)\n", key, i); exit(26); } else { suc_search += table_stats(test_table); suc_trials++; assert(*(int *)dp == key); } } } } for (i = 0; i < Trials; i++) { /* random key with uniform distribution */ key = (hashkey_t) (drand48() * key_range) + MINID; dp = table_retrieve(test_table, key); if (dp == NULL) { unsuc_search += table_stats(test_table); unsuc_trials++; } else { // this should be very rare assert(*(int *)dp == key); } } end = clock(); size = table_entries(test_table); printf(" After rehash, time=%g\n", 1000*((double)(end-start))/CLOCKS_PER_SEC); printf(" Measured avg probes for successful search=%g, trials=%d\n", (double) suc_search/suc_trials, suc_trials); printf(" Measured avg probes for unsuccessful search=%g, trials=%d\n", (double) unsuc_search/unsuc_trials, unsuc_trials); /* remove and free all items from table */ table_destruct(test_table); printf("----- End of equilibrium test -----\n\n"); }
/* driver to test small tables. This is a series of * simple tests and is not exhaustive. * * input: test_M is the table size for this test run */ void RehashDriver(int test_M) { int i, *ip, code; table_t *H; printf("\n----- Rehash driver -----\n"); if (ProbeDec == CHAIN) { printf("This design of the rehash driver does not work with separate chaining\n"); return; } hashkey_t startkey = MINID + (test_M - MINID%test_M); assert(startkey%test_M == 0); assert(test_M > 5); // tests designed for size at least 6 H = table_construct(test_M, ProbeDec); // fill table sequentially for (i = 0; i < test_M-1; i++) { ip = (int *) malloc(sizeof(int)); *ip = 10*i; assert(table_full(H) == 0); code = table_insert(H, startkey+i, ip); ip = NULL; assert(code == 0); assert(table_entries(H) == i+1); assert(table_stats(H) == 1); assert(table_peek(H,i,0) == startkey+i); } if (Verbose) { printf("\nfull table, last entry empty\n"); table_debug_print(H); } // tests on empty position assert(table_peek(H,i,0) == 0); assert(NULL == table_retrieve(H, startkey+i)); assert(table_stats(H) == 1); assert(table_full(H) == 1); assert(-1 == table_insert(H, MAXID, NULL)); // retrieve and replace each entry for (i = 0; i < test_M-1; i++) { ip = table_retrieve(H, startkey+i); assert(*(int *)ip == 10*i); ip = NULL; assert(table_stats(H) == 1); ip = table_retrieve(H, startkey+i+test_M); assert(ip == NULL); assert(2 <= table_stats(H) && table_stats(H) <= test_M); if (ProbeDec == LINEAR) assert(table_stats(H) == i+2); ip = (int *) malloc(sizeof(int)); *ip = 99*i; assert(1 == table_insert(H, startkey+i, ip)); ip = NULL; ip = table_retrieve(H, startkey+i); assert(*(int *)ip == 99*i); ip = NULL; } assert(table_entries(H) == test_M-1); assert(table_full(H) == 1); // delete tests assert(table_deletekeys(H) == 0); ip = table_delete(H, startkey+1); assert(*(int *)ip == 99); free(ip); ip = NULL; if (Verbose) { printf("\nsecond entry deleted, last entry empty\n"); table_debug_print(H); } assert(table_entries(H) == test_M-2); assert(table_full(H) == 0); assert(table_peek(H,1,0) == 0); assert(table_deletekeys(H) == 1); ip = table_retrieve(H, startkey+1); // check key is not there assert(ip == NULL); assert(table_stats(H) >= 2); // attempt to delete keys not in table assert(NULL == table_delete(H, startkey+1)); assert(NULL == table_delete(H, startkey+test_M-1)); // insert key in its place ip = (int *) malloc(sizeof(int)); *ip = 123; assert(0 == table_insert(H, startkey+1+test_M, ip)); ip = NULL; assert(table_peek(H,1,0) == startkey+1+test_M); ip = table_retrieve(H, startkey+1+test_M); assert(*(int *)ip == 123); ip = NULL; assert(table_entries(H) == test_M-1); assert(table_full(H) == 1); assert(table_deletekeys(H) == 0); for (i = 2; i < test_M-1; i++) { // clear out all but two keys ip = table_delete(H, startkey+i); assert(*(int *)ip == 99*i); free(ip); ip = NULL; } assert(table_entries(H) == 2); ip = (int *) malloc(sizeof(int)); // fill last empty *ip = 456; assert(0 == table_insert(H, startkey+test_M-1, ip)); ip = NULL; assert(table_entries(H) == 3); // unsuccessful search when no empty keys assert(NULL == table_retrieve(H, startkey+test_M)); // two keys the collide in position 0 ip = (int *) malloc(sizeof(int)); *ip = 77; assert(0 == table_insert(H, startkey+test_M, ip)); ip = (int *) malloc(sizeof(int)); *ip = 88; assert(0 == table_insert(H, startkey+10*test_M, ip)); ip = NULL; assert(table_entries(H) == 5); ip = table_delete(H, startkey); // delete position 0 assert(*(int *)ip == 0); free(ip); ip = NULL; assert(table_entries(H) == 4); ip = (int *) malloc(sizeof(int)); // replace *ip = 87; assert(1 == table_insert(H, startkey+10*test_M, ip)); ip = NULL; assert(table_entries(H) == 4); ip = (int *) malloc(sizeof(int)); // put back position 0 *ip = 76; assert(0 == table_insert(H, startkey+20*test_M, ip)); ip = NULL; assert(table_entries(H) == 5); assert(table_peek(H,0,0) == startkey+20*test_M); assert(table_deletekeys(H) == test_M-5); // verify 5 items in table ip = table_retrieve(H, startkey+1+test_M); assert(*(int *)ip == 123); ip = table_retrieve(H, startkey+test_M); assert(*(int *)ip == 77); ip = table_retrieve(H, startkey+10*test_M); assert(*(int *)ip == 87); ip = table_retrieve(H, startkey+20*test_M); assert(*(int *)ip == 76); ip = table_retrieve(H, startkey+test_M-1); assert(*(int *)ip == 456); ip = NULL; // rehash H = table_rehash(H, test_M); assert(table_entries(H) == 5); assert(table_deletekeys(H) == 0); if (Verbose) { printf("\ntable after rehash with 5 items\n"); table_debug_print(H); } // verify 5 items in table ip = table_retrieve(H, startkey+1+test_M); assert(*(int *)ip == 123); ip = table_retrieve(H, startkey+test_M); assert(*(int *)ip == 77); ip = table_retrieve(H, startkey+10*test_M); assert(*(int *)ip == 87); ip = table_retrieve(H, startkey+20*test_M); assert(*(int *)ip == 76); ip = table_retrieve(H, startkey+test_M-1); assert(*(int *)ip == 456); ip = NULL; // rehash and increase table size // If linear double the size // If double, need new prime int new_M = 2*test_M; if (ProbeDec == DOUBLE) new_M = find_first_prime(new_M); H = table_rehash(H, new_M); assert(table_entries(H) == 5); assert(table_deletekeys(H) == 0); if (Verbose) { printf("\nafter increase table to %d with 5 items\n", new_M); table_debug_print(H); } // verify 5 keys and information not lost during rehash ip = table_retrieve(H, startkey+1+test_M); assert(*(int *)ip == 123); ip = table_retrieve(H, startkey+test_M); assert(*(int *)ip == 77); ip = table_retrieve(H, startkey+10*test_M); assert(*(int *)ip == 87); ip = table_retrieve(H, startkey+20*test_M); assert(*(int *)ip == 76); ip = table_retrieve(H, startkey+test_M-1); assert(*(int *)ip == 456); ip = NULL; // fill the new larger table assert(table_full(H) == 0); int new_items = new_M - 1 - 5; int base_addr = 2*startkey + 20*test_M*test_M; if (base_addr+new_items*test_M > MAXID) { printf("re-run -b driver with smaller table size\n"); exit(1); } for (i = 0; i < new_items; i++) { ip = (int *) malloc(sizeof(int)); *ip = 10*i; code = table_insert(H, base_addr+i*test_M, ip); ip = NULL; assert(code == 0); assert(table_entries(H) == i+1+5); } assert(table_full(H) == 1); assert(table_entries(H) == new_M-1); if (Verbose) { printf("\nafter larger table filled\n"); table_debug_print(H); } // verify new items are found for (i = 0; i < new_items; i++) { ip = table_retrieve(H, base_addr+i*test_M); assert(*(int *)ip == 10*i); ip = NULL; } // clean up table table_destruct(H); printf("----- Passed rehash driver -----\n\n"); }