Commit 0299a20f authored by Jonathan Jenkins's avatar Jonathan Jenkins
Browse files

codes mapping overhaul to support annotations

Contains the following:
- annotation-aware codes-mapping API
- updated mapping tests
- updated codes-base models to use the new API
- updated LSM to configure based on annotation
  - fixed initialization issue (was doing config as an event)
  - no need for lsm_send_init from outside LPs
parent b2d7138f
......@@ -22,36 +22,128 @@ tw_peid codes_mapping( tw_lpid gid);
void codes_mapping_setup(void);
/*Takes the group name and returns the number of repetitions in the group */
int codes_mapping_get_group_reps(char* grp_name);
int codes_mapping_get_group_reps(const char* group_name);
/* Takes the group name and lp type name, returns the count for that lp type */
int codes_mapping_get_lp_count(char* grp_name, char* lp_type_name);
/* Gets the total lp type count across all groups */
int codes_mapping_get_global_lp_count(char* lp_type_name);
/* Calculates the count for LPs of the given type
*
* group_name - name of group. If NULL, count is across all groups.
* ignore_repetitions - if group_name is given, then don't include repetitions
* in count. This exists at the moment to support some
* uses of the function that haven't been fleshed out in
* other parts of the API (used by the dragonfly/torus
* models)
* lp_type_name - name of LP type
* annotation - optional annotation. If NULL, entry is considered
* unannotated
* ignore_annos - If non-zero, then count across all annotations (and
* ignore whatever annotation parameter is passed in)
*
* returns the number of LPs found (0 in the case of some combination of group,
* lp_type_name, and annotation not being found)
*/
int codes_mapping_get_lp_count(
const char * group_name,
int ignore_repetitions,
const char * lp_type_name,
const char * annotation,
int ignore_annos);
/* Takes the group name , type name, rep ID and offset (for that lp type + repetition) and then returns the global LP ID. */
void codes_mapping_get_lp_id(char* grp_name, char* lp_type_name, int rep_id, int offset, tw_lpid* gid);
/* Calculates the global LP ID given config identifying info.
*
* group_name - name of group
* lp_type_name - name of LP type
* annotation - optional annotation (NULL -> unannotated)
* ignore_anno - ignores annotation and sets gid to the first found LP type
* with matching names
* rep_id - repetition within the group
* offset - lp offset within the repetition
* gid - output ID
*
* If the LP is unable to be found, a tw_error will occur
*/
void codes_mapping_get_lp_id(
const char * group_name,
const char * lp_type_name,
const char * annotation,
int ignore_anno,
int rep_id,
int offset,
tw_lpid * gid);
/* Takes the LP ID and returns its logical ID across LPs of the same type in
* all groups */
int codes_mapping_get_lp_global_rel_id(tw_lpid gid);
/* Calculates the LP ID relative to other LPs (0..N-1, where N is the number of
* LPs sharing the same type)
*
* gid - LP ID
* group_wise - whether to compute id relative to the LP's group
* annotation_wise - whether to compute id relative to the annotation the LP has
*/
int codes_mapping_get_lp_relative_id(
tw_lpid gid,
int group_wise,
int annotation_wise);
/* takes the LP ID and returns its grp name and index, lp type name and ID, repetition ID and the offset of the LP
* (for multiple LPs in a repetition). */
void codes_mapping_get_lp_info(tw_lpid gid, char* grp_name, int* grp_id, int* lp_type_id, char* lp_type_name, int* grp_rep_id, int* offset);
/* Returns configuration group information for a given LP-id
*
* gid - LP to look up
* group_name - output LP group name
* group_index - index in config struct of group (mostly used internally)
* lp_type_name - output LP type name
* lp_type_index - index in config struct of lp type (mostly used internally)
* annotation - output annotation (given that the caller is responsible for
* providing the memory, if there's no annotation then the empty
* string is returned)
* rep_id - output repetition within the group
* offset - output LP offset within the LP (for multiple lps in a rep.)
*
* The *_name and annotation parameters can be NULL, in which case the result
* strings aren't copied to them. This is useful when you just need the
* repetition ID and/or the offset. Otherwise, the caller is expected to pass in
* properly-allocated buffers for each (of size MAX_NAME_LENGTH)
*/
void codes_mapping_get_lp_info(
tw_lpid gid,
char * group_name,
int * group_index,
char * lp_type_name,
int * lp_type_index,
char * annotation,
int * rep_id,
int * offset);
//void codes_mapping_get_lp_info(tw_lpid gid, char* group_name, int* grp_id, int* lp_type_id, char* lp_type_name, int* grp_rep_id, int* offset);
/* given the group and LP type name, return the annotation (or NULL if there is
* none) */
const char* codes_mapping_get_annotation_by_name(char *grp_name, char *lp_type_name);
/* given the LP ID, return the annotation (or NULL if there is none)
* NOTE: both functions have equivalent results. The different ways of accessing
* are for convenience */
/* Returns the annotation for the given LP.
*
* group_name - group name of LP
* lp_type_name - name of the LP
*
* NOTE: This function returns the annotation for the first found LP with
* lp_type_name within the group. In the case of having multiple LP types with
* different annotations in the same group, use the _by_lpid version.
*
* Either the annotation string or NULL (in the case of an unannotated entry) is
* returned. */
const char* codes_mapping_get_annotation_by_name(
const char * group_name,
const char * lp_type_name);
/* Returns the annotation for the given LP.
*
* gid - LP id to look up
*
* NOTE: both functions have equivalent results if there is only one LP type in
* the requested group. The different ways of accessing are for convenience.
* This function is the one to use if there are multiple group entries of the
* same LP type (and different annotations)
*
* Either the annotation string or NULL (in the case of an unannotated entry) is
* returned. */
const char* codes_mapping_get_annotation_by_lpid(tw_lpid gid);
/*
* Returns a mapping of LP name to all annotations used with the type
*
* lp_name - lp name as used in the configuration
* lp_name - lp name as used in the configuration
*/
const config_anno_map_t *
codes_mapping_get_lp_anno_map(const char *lp_name);
......
......@@ -9,13 +9,14 @@
#include <ross.h>
#define LSM_NAME "lsm"
/*
* lsm_event_t
* - events supported by the local storage model
*/
typedef enum lsm_event_e
{
LSM_INIT = 0,
LSM_WRITE_REQUEST = 1,
LSM_READ_REQUEST = 2,
LSM_WRITE_COMPLETION = 3,
......@@ -41,7 +42,8 @@ tw_event* lsm_event_new(const char* category,
void* lsm_event_data(tw_event *event);
void lsm_init(void);
void lsm_register(void);
void lsm_configure(void);
void lsm_send_init (tw_lpid gid, tw_lp *lp, char *name);
......
......@@ -23,6 +23,7 @@
#include "codes/configuration.h"
#include "codes/model-net.h"
#include "codes/lp-type-lookup.h"
#include "codes/local-storage-model.h"
static int num_reqs = 0;/* number of requests sent by each server (read from config) */
static int payload_sz = 0; /* size of simulated data payload, bytes (read from config) */
......@@ -237,8 +238,9 @@ int main(
* codes */
codes_mapping_setup();
/* calculate the number of servers in this simulation */
num_servers = codes_mapping_get_group_reps(group_name) * codes_mapping_get_lp_count(group_name, "server");
/* calculate the number of servers in this simulation,
* ignoring annotations */
num_servers = codes_mapping_get_lp_count(group_name, 0, "server", NULL, 1);
/* for this example, we read from a separate configuration group for
* server message parameters. Since they are constant for all LPs,
......@@ -391,18 +393,20 @@ tw_lpid get_next_server(tw_lpid sender_id)
/* first, get callers LP and group info from codes-mapping. Caching this
* info in the LP struct isn't a bad idea for preventing a huge number of
* lookups */
char grp_name[MAX_NAME_LENGTH], lp_type_name[MAX_NAME_LENGTH];
char grp_name[MAX_NAME_LENGTH], lp_type_name[MAX_NAME_LENGTH],
annotation[MAX_NAME_LENGTH];
int lp_type_id, grp_id, grp_rep_id, offset, num_reps;
int dest_rep_id;
codes_mapping_get_lp_info(sender_id, grp_name, &grp_id, &lp_type_id,
lp_type_name, &grp_rep_id, &offset);
codes_mapping_get_lp_info(sender_id, grp_name, &grp_id, lp_type_name,
&lp_type_id, annotation, &grp_rep_id, &offset);
/* in this example, we assume that, for our group of servers, each
* "repetition" consists of a single server/NIC pair. Hence, we grab the
* server ID for the next repetition, looping around if necessary */
num_reps = codes_mapping_get_group_reps(grp_name);
dest_rep_id = (grp_rep_id+1) % num_reps;
/* finally, get the server (exactly 1 server per rep -> offset w/in rep = 0 */
codes_mapping_get_lp_id(grp_name, lp_type_name, dest_rep_id, 0, &rtn_id);
codes_mapping_get_lp_id(grp_name, lp_type_name, NULL, 1, dest_rep_id,
0, &rtn_id);
return rtn_id;
}
......
This diff is collapsed.
......@@ -392,11 +392,13 @@ int configuration_get_lpgroups (ConfigHandle *handle,
* given annotation. Used for configuration schemes where an array of
* configuration values is generated based on the annotations in
* config_anno_map_t
* If annotation is not found, -1 is returned */
* If anno is not found or a NULL anno is passed in,
* -1 is returned */
int configuration_get_annotation_index(const char * anno,
const config_anno_map_t * anno_map){
if (anno == NULL) return -1;
for (uint64_t i = 0; i < anno_map->num_annos; i++){
if (strcmp(anno, anno_map->annotations[i]) == 0){
if (!strcmp(anno, anno_map->annotations[i])){
return (int)i;
}
}
......
......@@ -146,6 +146,10 @@ static void write_stats(tw_lp* lp, lsm_stats_t* stat);
static int lsm_magic = 0;
/* configuration parameters (by annotation) */
static disk_model_t model_unanno, *models_anno = NULL;
static const config_anno_map_t *anno_map = NULL;
/*
* lsm_lp
* - implements ROSS callback interfaces
......@@ -160,120 +164,6 @@ tw_lptype lsm_lp =
sizeof(lsm_state_t)
};
/*
* lsm_load_config
* - load configuration disk parameters
*/
static void lsm_load_config (ConfigHandle *ch, char *name, lsm_state_t *ns, tw_lp *lp)
{
disk_model_t *model;
char **values;
size_t length;
int rc;
int i;
model = (disk_model_t *) malloc(sizeof(disk_model_t));
assert(model);
// get my annotation (if any)
const char *anno = codes_mapping_get_annotation_by_lpid(lp->gid);
// request sizes
rc = configuration_get_multivalue(ch, name, "request_sizes", anno,
&values,&length);
assert(rc == 1);
model->request_sizes = malloc(sizeof(int)*length);
assert(model->request_sizes);
model->bins = length;
for (i = 0; i < length; i++)
{
model->request_sizes[i] = atoi(values[i]);
}
free(values);
// write rates
rc = configuration_get_multivalue(ch, name, "write_rates", anno,
&values,&length);
assert(rc == 1);
model->write_rates = malloc(sizeof(double)*length);
assert(model->write_rates);
assert(length == model->bins);
for (i = 0; i < length; i++)
{
model->write_rates[i] = strtod(values[i], NULL);
}
free(values);
// read rates
rc = configuration_get_multivalue(ch, name, "read_rates", anno,
&values,&length);
assert(rc == 1);
model->read_rates = malloc(sizeof(double)*length);
assert(model->read_rates);
assert(model->bins == length);
for (i = 0; i < length; i++)
{
model->read_rates[i] = strtod(values[i], NULL);
}
free(values);
// write overheads
rc = configuration_get_multivalue(ch, name, "write_overheads", anno,
&values,&length);
assert(rc == 1);
model->write_overheads = malloc(sizeof(double)*length);
assert(model->write_overheads);
assert(model->bins == length);
for (i = 0; i < length; i++)
{
model->write_overheads[i] = strtod(values[i], NULL);
}
free(values);
// read overheades
rc = configuration_get_multivalue(ch, name, "read_overheads", anno,
&values,&length);
assert(rc == 1);
model->read_overheads = malloc(sizeof(double)*length);
assert(model->read_overheads);
assert(model->bins == length);
for (i = 0; i < length; i++)
{
model->read_overheads[i] = strtod(values[i], NULL);
}
free(values);
// write seek latency
rc = configuration_get_multivalue(ch, name, "write_seeks", anno,
&values,&length);
assert(rc == 1);
model->write_seeks = malloc(sizeof(double)*length);
assert(model->write_seeks);
assert(model->bins == length);
for (i = 0; i < length; i++)
{
model->write_seeks[i] = strtod(values[i], NULL);
}
free(values);
// read seek latency
rc = configuration_get_multivalue(ch, name, "read_seeks", anno,
&values,&length);
assert(rc == 1);
model->read_seeks = malloc(sizeof(double)*length);
assert(model->read_seeks);
assert(model->bins == length);
for (i = 0; i < length; i++)
{
model->read_seeks[i] = strtod(values[i], NULL);
}
free(values);
ns->model = model;
return;
}
static tw_stime transfer_time_table (lsm_state_t *ns,
lsm_stats_t *stat,
int rw,
......@@ -348,37 +238,6 @@ static tw_stime transfer_time_table (lsm_state_t *ns,
return time;
}
/*
* lsm_send_init
* - generates an init event with supplies parameters
* - no ack is generated
*/
void lsm_send_init (tw_lpid gid,
tw_lp *lp,
char *diskname)
{
tw_lpid lsm_gid;
tw_event *e;
lsm_message_t *m;
char lp_type_name[MAX_NAME_LENGTH], lp_group_name[MAX_NAME_LENGTH];
int mapping_grp_id, mapping_rep_id, mapping_type_id, mapping_offset;
tw_stime offset;
codes_mapping_get_lp_info(gid, lp_group_name, &mapping_grp_id,
&mapping_type_id, lp_type_name, &mapping_rep_id, &mapping_offset);
codes_mapping_get_lp_id("TRITON_GRP", "lsm", mapping_rep_id,
mapping_offset, &lsm_gid);
offset = codes_local_latency(lp);
e = codes_event_new(lsm_gid, offset, lp);
m = tw_event_data(e);
m->magic = lsm_magic;
m->event = LSM_INIT;
strncpy(m->u.init.name, (diskname) ? diskname : "lsm", sizeof(m->u.init.name));
tw_event_send(e);
}
void lsm_event_new_reverse(tw_lp *sender)
{
codes_local_latency_reverse(sender);
......@@ -389,22 +248,23 @@ void lsm_event_new_reverse(tw_lp *sender)
* lsm_find_local_device()
*
* returns the LP id of the lsm device connected to the caller
*
* TODO: currently ignores annotations
*/
tw_lpid lsm_find_local_device(tw_lp *sender)
{
char lp_type_name[MAX_NAME_LENGTH], lp_group_name[MAX_NAME_LENGTH];
int mapping_grp_id, mapping_rep_id, mapping_type_id, mapping_offset;
char lp_group_name[MAX_NAME_LENGTH];
int mapping_rep_id, mapping_offset, dummy;
tw_lpid lsm_gid;
codes_mapping_get_lp_info(sender->gid, lp_group_name, &mapping_grp_id,
&mapping_type_id, lp_type_name, &mapping_rep_id, &mapping_offset);
codes_mapping_get_lp_id("TRITON_GRP", "lsm", mapping_rep_id,
codes_mapping_get_lp_info(sender->gid, lp_group_name, &dummy,
NULL, &dummy, NULL, &mapping_rep_id, &mapping_offset);
codes_mapping_get_lp_id(lp_group_name, LSM_NAME, NULL, 1, mapping_rep_id,
mapping_offset, &lsm_gid);
return(lsm_gid);
}
/*
* lsm_event_new
* - creates a new event that is targeted for the corresponding
......@@ -433,8 +293,6 @@ tw_event* lsm_event_new(const char* category,
tw_event *e;
lsm_message_t *m;
tw_lpid lsm_gid;
char lp_type_name[MAX_NAME_LENGTH], lp_group_name[MAX_NAME_LENGTH];
int mapping_grp_id, mapping_rep_id, mapping_type_id, mapping_offset;
assert(strlen(category) < CATEGORY_NAME_MAX-1);
assert(strlen(category) > 0);
......@@ -442,10 +300,7 @@ tw_event* lsm_event_new(const char* category,
/* Generate an event for the local storage model, and send the
* event to an lsm LP.
*/
codes_mapping_get_lp_info(sender->gid, lp_group_name, &mapping_grp_id,
&mapping_type_id, lp_type_name, &mapping_rep_id, &mapping_offset);
codes_mapping_get_lp_id("TRITON_GRP", "lsm", mapping_rep_id,
mapping_offset, &lsm_gid);
lsm_gid = lsm_find_local_device(sender);
e = codes_event_new(lsm_gid, codes_local_latency(sender)+delay, sender);
m = tw_event_data(e);
......@@ -484,7 +339,6 @@ void* lsm_event_data(tw_event *event)
* lsm_lp_init
* - initialize the lsm model
* - sets the disk to be idle now
* - other parameters must be set through init event
*/
static void lsm_lp_init (lsm_state_t *ns, tw_lp *lp)
{
......@@ -492,6 +346,15 @@ static void lsm_lp_init (lsm_state_t *ns, tw_lp *lp)
ns->next_idle = tw_now(lp);
// set the correct model
const char *anno = codes_mapping_get_annotation_by_lpid(lp->gid);
if (anno == NULL)
ns->model = &model_unanno;
else {
int id = configuration_get_annotation_index(anno, anno_map);
ns->model = &models_anno[id];
}
return;
}
......@@ -507,13 +370,6 @@ static void lsm_event (lsm_state_t *ns, tw_bf *b, lsm_message_t *m, tw_lp *lp)
switch (m->event)
{
case LSM_INIT:
if (LSM_DEBUG)
printf("svr(%llu): INIT name:%s\n",
(unsigned long long)lp->gid,
m->u.init.name);
lsm_load_config(&config, m->u.init.name, ns, lp);
break;
case LSM_WRITE_REQUEST:
case LSM_READ_REQUEST:
if (LSM_DEBUG)
......@@ -555,13 +411,6 @@ static void lsm_rev_event(lsm_state_t *ns,
switch (m->event)
{
case LSM_INIT:
if (LSM_DEBUG)
printf("svr(%llu): reverse INIT name:%s\n",
(unsigned long long)lp->gid,
m->u.init.name);
if (ns->model) free(ns->model);
break;
case LSM_WRITE_REQUEST:
case LSM_READ_REQUEST:
if (LSM_DEBUG)
......@@ -814,14 +663,129 @@ static void write_stats(tw_lp* lp, lsm_stats_t* stat)
}
void lsm_init(void)
void lsm_register(void)
{
uint32_t h1=0, h2=0;
bj_hashlittle2("localstorage", strlen("localstorage"), &h1, &h2);
lsm_magic = h1+h2;
lp_type_register("lsm", &lsm_lp);
lp_type_register(LSM_NAME, &lsm_lp);
}
// read the configuration file for a given annotation
static void read_config(ConfigHandle *ch, char * anno, disk_model_t *model)
{
char **values;
size_t length;
int rc;
// request sizes
rc = configuration_get_multivalue(ch, LSM_NAME, "request_sizes", anno,
&values,&length);
assert(rc == 1);
model->request_sizes = malloc(sizeof(int)*length);
assert(model->request_sizes);
model->bins = length;
for (int i = 0; i < length; i++)
{
model->request_sizes[i] = atoi(values[i]);
}
free(values);
// write rates
rc = configuration_get_multivalue(ch, LSM_NAME, "write_rates", anno,
&values,&length);
assert(rc == 1);
model->write_rates = malloc(sizeof(double)*length);
assert(model->write_rates);
assert(length == model->bins);
for (int i = 0; i < length; i++)
{
model->write_rates[i] = strtod(values[i], NULL);
}
free(values);
// read rates
rc = configuration_get_multivalue(ch, LSM_NAME, "read_rates", anno,
&values,&length);
assert(rc == 1);
model->read_rates = malloc(sizeof(double)*length);
assert(model->read_rates);
assert(model->bins == length);
for (int i = 0; i < length; i++)
{
model->read_rates[i] = strtod(values[i], NULL);
}
free(values);
// write overheads
rc = configuration_get_multivalue(ch, LSM_NAME, "write_overheads", anno,
&values,&length);
assert(rc == 1);
model->write_overheads = malloc(sizeof(double)*length);
assert(model->write_overheads);
assert(model->bins == length);
for (int i = 0; i < length; i++)
{
model->write_overheads[i] = strtod(values[i], NULL);
}
free(values);
// read overheades
rc = configuration_get_multivalue(ch, LSM_NAME, "read_overheads", anno,
&values,&length);
assert(rc == 1);
model->read_overheads = malloc(sizeof(double)*length);
assert(model->read_overheads);
assert(model->bins == length);
for (int i = 0; i < length; i++)
{
model->read_overheads[i] = strtod(values[i], NULL);
}
free(values);
// write seek latency
rc = configuration_get_multivalue(ch, LSM_NAME, "write_seeks", anno,
&values,&length);
assert(rc == 1);
model->write_seeks = malloc(sizeof(double)*length);
assert(model->write_seeks);
assert(model->bins == length);
for (int i = 0; i < length; i++)
{
model->write_seeks[i] = strtod(values[i], NULL);
}
free(values);
// read seek latency
rc = configuration_get_multivalue(ch, LSM_NAME, "read_seeks", anno,
&values,&length);
assert(rc == 1);
model->read_seeks = malloc(sizeof(double)*length);
assert(model->read_seeks);