Commit 46a52a04 authored by Robert Ricci's avatar Robert Ricci

Add some new ways to treat features.

Features that begin with a '*' have some kind of global scope. Since
that, by itself, doesn't mean much, the second character of the
feature name must tell us what type of global feature it is. The two
currently supported are:

'&' - 'one is okay' - don't penalize the first pnode that has this
    feature, but penalize subsequent ones. Will be used to prefer
    not to give people multiple nodes at the sime widearea site.
'!' - 'more than one is okay' - penalize the first pnode that has
    this feature, but not subsequent ones. This could be used to let
    assign pick experiments to swap out in order to let the current
    experiment map. The idea being that once you've decided that one
    of the experiment's nodes is getting stolen, you might as well
    swap the whole thing.

For now, these global features should not have corresponding desires,
because it's not clear what the right thing to do would be. But, we may
decide to add these semantics someday.
parent 74846b81
......@@ -56,7 +56,9 @@ bool find_link_to_switch(pvertex pv,pvertex switch_pv,tb_vlink *vlink,
int find_interswitch_path(pvertex src_pv,pvertex dest_pv,
int bandwidth,pedge_path &out_path,
pvertex_list &out_switches);
double fd_score(tb_vnode *vnode,tb_pnode *pnoder,int &out_fd_violated);
double fd_score(tb_vnode *vnode,tb_pnode *pnode,int &out_fd_violated);
inline void add_global_fds(tb_vnode *vnode,tb_pnode *pnode);
inline void remove_global_fds(tb_vnode *vnode,tb_pnode *pnode);
void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode,
tb_vnode *src_vnode, tb_vnode *dst_vnode);
void unscore_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode,
......@@ -84,6 +86,12 @@ void score_link_endpoints(pedge pe);
#define SDEBUG(a)
#endif
/*
* For features and desires that have a some sort of global impact
*/
typedef hash_map<crope,unsigned int> fd_count_map;
fd_count_map global_fd_set;
/*
* score()
* Returns the score.
......@@ -455,6 +463,7 @@ void remove_node(vvertex vv)
*/
int fd_violated;
double fds=fd_score(vnode,pnode,fd_violated);
remove_global_fds(vnode,pnode);
SSUB(fds);
violated -= fd_violated;
vinfo.desires -= fd_violated;
......@@ -1013,6 +1022,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic)
violated--;
// features/desires
add_global_fds(vnode,pnode);
int fd_violated;
double fds = fd_score(vnode,pnode,fd_violated);
SADD(fds);
......@@ -1496,17 +1506,53 @@ double fd_score(tb_vnode *vnode,tb_pnode *pnode,int &fd_violated)
if (!pnode->features.empty()) {
for (feature_it = pnode->features.begin();
feature_it != pnode->features.end();++feature_it) {
desire_it = vnode->desires.find((*feature_it).first);
SDEBUG(cerr << " feature = " << (*feature_it).first
crope feature_name = (*feature_it).first;
value = (*feature_it).second;
SDEBUG(cerr << " feature = " << feature_name
<< " " << (*feature_it).second << endl);
if (desire_it == vnode->desires.end()) {
// Unused feature. Add weight
SDEBUG(cerr << " unused" << endl);
value = (*feature_it).second;
fd_score+=SCORE_FEATURE*value;
if (value >= FD_VIOLATION_WEIGHT) {
fd_violated++;
if (feature_name[0] == '*') {
SDEBUG(cerr << " global" << endl);
// Handle features with global scope - for now, these don't have
// desires to go with them, but we may want to change that at some
// point
switch (feature_name[1]) {
case '&': // A 'one is okay' feature - only score if we have more
// than one pnode with this feature
SDEBUG(cerr << " 'one is okay'" << endl);
if (global_fd_set[feature_name] > 1) {
SDEBUG(cerr << " but more than one" << endl);
fd_score+=SCORE_FEATURE*value;
if (value >= FD_VIOLATION_WEIGHT) {
fd_violated++;
}
}
break;
case '!': // A 'more than one is okay' feature - if we already have one,
// a second doesn't incur further penalty
SDEBUG(cerr << " ' more than one is okay'" << endl);
if (global_fd_set[feature_name] == 1) {
SDEBUG(cerr << " but only one" << endl);
fd_score+=SCORE_FEATURE*value;
if (value >= FD_VIOLATION_WEIGHT) {
fd_violated++;
}
}
break;
default:
// Global features are required to have some kind of type
cerr << "Bad global feature " << (*feature_it).first << endl;
exit(2);
}
} else {
desire_it = vnode->desires.find(feature_name);
if (desire_it == vnode->desires.end()) {
// Unused feature. Add weight
SDEBUG(cerr << " unused" << endl);
fd_score+=SCORE_FEATURE*value;
if (value >= FD_VIOLATION_WEIGHT) {
fd_violated++;
}
}
}
}
......@@ -1516,6 +1562,36 @@ double fd_score(tb_vnode *vnode,tb_pnode *pnode,int &fd_violated)
return fd_score;
}
/*
* For now, in these function, which simply keep the global_fd_set
* data structure up to date, we ignore vnodes desires - however, we may
* decide to change this someday if we use global features for some other
* purpose
*/
void add_global_fds(tb_vnode *vnode,tb_pnode *pnode) {
tb_pnode::features_map::iterator feature_it;
if (!pnode->features.empty()) {
for (feature_it = pnode->features.begin();
feature_it != pnode->features.end();++feature_it) {
if (feature_it->first[0] == '*') {
global_fd_set[feature_it->first]++;
}
}
}
}
void remove_global_fds(tb_vnode *vnode,tb_pnode *pnode) {
tb_pnode::features_map::iterator feature_it;
if (!pnode->features.empty()) {
for (feature_it = pnode->features.begin();
feature_it != pnode->features.end();++feature_it) {
if (feature_it->first[0] == '*') {
global_fd_set[feature_it->first]--;
assert(global_fd_set[feature_it->first] >= 0);
}
}
}
}
/* make_lan_node(vvertex vv)
* This routines create a physical lan node and connects it to a switch
* with a LAN plink. Most of the code is in determining which switch to
......
......@@ -76,7 +76,6 @@ void init_score();
void remove_node(vvertex vv);
int add_node(vvertex vv,pvertex pv,bool deterministic);
double get_score();
double fd_score(tb_vnode &vnoder,tb_pnode &pnoder,int *fd_violated);
pvertex make_lan_node(vvertex vv);
void delete_lan_node(pvertex pv);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment