Esempio n. 1
0
CpuAttributes* buildSlot( MachAttributes *m_attr, int slot_id, StringList* list, int type, bool except )
{
    typedef CpuAttributes::slotres_map_t slotres_map_t;
	int cpus = UNSET_SHARE;
    int ram = UNSET_SHARE;
	float disk = UNSET_SHARE;
    float swap = UNSET_SHARE;
    float share;
    slotres_map_t slotres;
	float default_share = AUTO_SHARE;

	MyString execute_dir, partition_id;
	GetConfigExecuteDir( slot_id, &execute_dir, &partition_id );

	if ( list == NULL) {
	  // give everything the default share and return

	  cpus = compute_cpus( m_attr->num_cpus(), default_share );
	  ram = compute_phys_mem( m_attr, default_share );
	  swap = default_share;
	  disk = default_share;

      for (slotres_map_t::const_iterator j(m_attr->machres().begin());  j != m_attr->machres().end();  ++j) {
          slotres[j->first] = default_share;
      }

	  return new CpuAttributes( m_attr, type, cpus, ram, swap, disk, slotres, execute_dir, partition_id );
	}
		// For this parsing code, deal with the following example
		// string list:
		// "c=1, r=25%, d=1/4, s=25%"
		// There may be a bare number (no equals sign) that specifies
		// the default share for any items not explicitly defined.  Example:
		// "c=1, 25%"

    for (slotres_map_t::const_iterator j(m_attr->machres().begin());  j != m_attr->machres().end();  ++j) {
        slotres[j->first] = AUTO_RES;
    }

	list->rewind();
	while (char* attrp = list->next()) {
        string attr_expr = attrp;
        string::size_type eqpos = attr_expr.find('=');
		if (string::npos == eqpos) {
				// There's no = in this description, it must be one
				// percentage or fraction for all attributes.
				// For example "1/4" or "25%".  So, we can just parse
				// it as a percentage and use that for everything.
			default_share = parse_value(attr_expr.c_str(), type, except);
			if( default_share <= 0 && !IS_AUTO_SHARE(default_share) ) {
				dprintf( D_ALWAYS, "ERROR: Bad description of slot type %d: ",
						 type );
				dprintf( D_ALWAYS | D_NOHEADER,  "\"%s\" is invalid.\n", attr_expr.c_str() );
				dprintf( D_ALWAYS | D_NOHEADER,
						 "\tYou must specify a percentage (like \"25%%\"), " );
				dprintf( D_ALWAYS | D_NOHEADER, "a fraction (like \"1/4\"),\n" );
				dprintf( D_ALWAYS | D_NOHEADER,
						 "\tor list all attributes (like \"c=1, r=25%%, s=25%%, d=25%%\").\n" );
				dprintf( D_ALWAYS | D_NOHEADER,
						 "\tSee the manual for details.\n" );
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			}
			continue;
		}

			// If we're still here, this is part of a string that
			// lists out seperate attributes and the share for each one.

			// Get the value for this attribute.  It'll either be a
			// percentage, or it'll be a distinct value (in which
			// case, parse_value() will return negative.
        string val = attr_expr.substr(1+eqpos);
		if (val.empty()) {
			dprintf(D_ALWAYS, "Can't parse attribute \"%s\" in description of slot type %d\n",
					attr_expr.c_str(), type);
			if( except ) {
				DC_Exit( 4 );
			} else {
				return NULL;
			}
		}
		share = parse_value(val.c_str(), type, except);

		// Figure out what attribute we're dealing with.
        string attr = attr_expr.substr(0, eqpos);
        slotres_map_t::const_iterator f(m_attr->machres().find(attr));
        if (f != m_attr->machres().end()) {
            slotres[f->first] = compute_local_resource(share, attr, m_attr->machres());
            continue;
        }
		switch( tolower(attr[0]) ) {
		case 'c':
			cpus = compute_cpus( m_attr->num_cpus(), share );
			break;
		case 'r':
		case 'm':
			ram = compute_phys_mem( m_attr, share );
			break;
		case 's':
		case 'v':
			if( share >= 0 || IS_AUTO_SHARE(share) ) {
				swap = share;
			} else {
				dprintf( D_ALWAYS,
						 "You must specify a percent or fraction for swap in slot type %d\n",
						 type );
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			}
			break;
		case 'd':
			if( share >= 0 || IS_AUTO_SHARE(share) ) {
				disk = share;
			} else {
				dprintf( D_ALWAYS,
						 "You must specify a percent or fraction for disk in slot type %d\n",
						type );
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			}
			break;
		default:
			dprintf( D_ALWAYS, "Unknown attribute \"%s\" in slot type %d\n",
					 attr.c_str(), type );
			if( except ) {
				DC_Exit( 4 );
			} else {
				return NULL;
			}
			break;
		}
	}

		// We're all done parsing the string.  Any attribute not
		// listed will get the default share.
	if (IS_UNSET_SHARE(cpus)) {
		cpus = compute_cpus( m_attr->num_cpus(), default_share );
	}
	if (IS_UNSET_SHARE(ram)) {
		ram = compute_phys_mem( m_attr, default_share );
	}
	if (IS_UNSET_SHARE(swap)) {
		swap = default_share;
	}
	if (IS_UNSET_SHARE(disk)) {
		disk = default_share;
	}
    for (slotres_map_t::iterator j(slotres.begin());  j != slotres.end();  ++j) {
        if (int(j->second) == AUTO_RES) {
            j->second = compute_local_resource(default_share, j->first, m_attr->machres());
        }
    }

		// Now create the object.
	return new CpuAttributes( m_attr, type, cpus, ram, swap, disk, slotres, execute_dir, partition_id );
}
Esempio n. 2
0
CpuAttributes* buildSlot( MachAttributes *m_attr, int slot_id, StringList* list, int type, bool except )
{
    typedef CpuAttributes::slotres_map_t slotres_map_t;
	double cpus = UNSET_SHARE;
	int ram = UNSET_SHARE; // this is in MB so an int is enough
	double disk_fraction = UNSET_SHARE;
	double swap_fraction = UNSET_SHARE;
	slotres_map_t slotres;
	special_share_t default_share_special = SPECIAL_SHARE_AUTO;
	double default_share = AUTO_SHARE;
	bool allow_fractional_cpu = false;

	MyString execute_dir, partition_id;
	GetConfigExecuteDir( slot_id, &execute_dir, &partition_id );

	if ( list == NULL) {
	  // give everything the default share and return

	  cpus = compute_local_resource(m_attr->num_cpus(), default_share, 1.0);
	  ram = compute_local_resource(m_attr->phys_mem(), default_share, 1);

      for (slotres_map_t::const_iterator j(m_attr->machres().begin());  j != m_attr->machres().end();  ++j) {
          slotres[j->first] = default_share;
      }

	  return new CpuAttributes( m_attr, type, cpus, ram, AUTO_SHARE, AUTO_SHARE, slotres, execute_dir, partition_id );
	}
		// For this parsing code, deal with the following example
		// string list:
		// "c=1, r=25%, d=1/4, s=25%"
		// There may be a bare number (no equals sign) that specifies
		// the default share for any items not explicitly defined.  Example:
		// "c=1, 25%"

    for (slotres_map_t::const_iterator j(m_attr->machres().begin());  j != m_attr->machres().end();  ++j) {
        slotres[j->first] = UNSET_SHARE;
    }

	list->rewind();
	while (char* attrp = list->next()) {
        string attr_expr = attrp;
        string::size_type eqpos = attr_expr.find('=');
		if (string::npos == eqpos) {
				// There's no = in this description, it must be one
				// percentage or fraction for all attributes.
				// For example "1/4" or "25%".  So, we can just parse
				// it as a percentage and use that for everything.
			default_share = parse_share_value(attr_expr.c_str(), type, except, default_share_special);
			if (default_share_special == SPECIAL_SHARE_NONE && (default_share < -1 || default_share > 0)) {
				dprintf( D_ALWAYS, "ERROR: Bad description of slot type %d: "
						"\"%s\" is invalid.\n"
						"\tYou must specify a percentage (like \"25%%\"), "
						"a fraction (like \"1/4\"),\n"
						"\tor list all attributes (like \"c=1, r=25%%, s=25%%, d=25%%\").\n"
						"\tSee the manual for details.\n",
						 type, attr_expr.c_str());
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			}
			if (default_share_special == SPECIAL_SHARE_MINIMAL) allow_fractional_cpu = true;
			continue;
		}

			// If we're still here, this is part of a string that
			// lists out seperate attributes and the share for each one.

			// Get the value for this attribute.  It'll either be a
			// percentage, or it'll be a distinct value (in which
			// case, parse_share_value() will return negative.
        string val = attr_expr.substr(1+eqpos);
		if (val.empty()) {
			dprintf(D_ALWAYS, "Can't parse attribute \"%s\" in description of slot type %d\n",
					attr_expr.c_str(), type);
			if( except ) {
				DC_Exit( 4 );
			} else {
				return NULL;
			}
		}
		special_share_t share_special = SPECIAL_SHARE_NONE;
		double share = parse_share_value(val.c_str(), type, except, share_special);

		// Figure out what attribute we're dealing with.
		string attr = attr_expr.substr(0, eqpos);
		trim(attr);
		slotres_map_t::const_iterator f(m_attr->machres().find(attr));
		if (f != m_attr->machres().end()) {
			slotres[f->first] = compute_local_resource(f->second, share);
			continue;
		}

		// before 8.1.4, only the first character of standard resource types
		// was looked at (case insensitively). This prevented us from detecting
		// typos in resource type names that start with c,r,m,s,v or d.
		// This code now compares the whole resource type name
		// But to preserve (most) of the pre 8.1.4 we will tolerate
		// any case-insensitive substring match of cpus, ram, memory, swap, virtualmemory, or disk
		int cattr = int(attr.length());
		if (MATCH == strncasecmp(attr.c_str(), "cpus", cattr))
		{
			double lower_bound = (allow_fractional_cpu) ? 0.0 : 1.0;
			cpus = compute_local_resource(m_attr->num_cpus(), share, lower_bound);
		} else if (
			MATCH == strncasecmp(attr.c_str(), "ram", cattr) ||
			MATCH == strncasecmp(attr.c_str(), "memory", cattr))
		{
			ram = compute_local_resource(m_attr->phys_mem(), share, 1);
		} else if (
			MATCH == strncasecmp(attr.c_str(), "swap", cattr) ||
			MATCH == strncasecmp(attr.c_str(), "virtualmemory", cattr))
		{
			// for now, we can only tolerate swap expressed a 'auto' or a proportion
			// because we don't know how much disk is available until later.
			if (share <= 0 || IS_AUTO_SHARE(share)) {
				swap_fraction = compute_local_resource(1.0, share);
			} else {
				dprintf( D_ALWAYS,
						 "You must specify a percent or fraction for swap in slot type %d\n",
						 type );
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			}
		} else if (
			MATCH == strncasecmp(attr.c_str(), "disk", cattr))
		{
			// for now, we can only tolerate swap expressed a 'auto' or a proportion
			// because we don't know how much disk is available until later.
			if (share <= 0 || IS_AUTO_SHARE(share)) {
				disk_fraction = compute_local_resource(1.0, share);
			} else {
				dprintf( D_ALWAYS,
						 "You must specify a percent or fraction for disk in slot type %d\n",
						type );
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			}

		} else {

			// at this point in the code a non-zero amount of the resource is requested only if share > 0.
			// requesting non-zero amounts of *unknown* resources is a fatal error
			// but requesting 0 or a share of the remainder isn't.  this makes it possible
			// to have a common config between machines that can be used to express things
			// like - "if this machine has GPUs, I don't want this slot to get any"..
			if (share > 0) {
				dprintf( D_ALWAYS, "Unknown attribute \"%s\" in slot type %d\n", attr.c_str(), type);
				if( except ) {
					DC_Exit( 4 );
				} else {
					return NULL;
				}
			} else {
				dprintf( D_ALWAYS | D_FULLDEBUG, "Unknown attribute \"%s\" in slot type %d, no resources will be allocated\n", attr.c_str(), type);
			}
		}
	}

	int std_resource_lower_bound = (allow_fractional_cpu) ? 0 : 1;

		// We're all done parsing the string.  Any attribute not
		// listed will get the default share.
	if (IS_UNSET_SHARE(cpus)) {
		cpus = compute_local_resource(m_attr->num_cpus(), default_share, (double)std_resource_lower_bound);
	}
	if (IS_UNSET_SHARE(ram)) {
		ram = compute_local_resource(m_attr->phys_mem(), default_share, std_resource_lower_bound);
	}
	if (IS_UNSET_SHARE(swap_fraction)) {
		swap_fraction = compute_local_resource(1.0, default_share);
	}
	if (IS_UNSET_SHARE(disk_fraction)) {
		disk_fraction = compute_local_resource(1.0, default_share);
	}
	for (slotres_map_t::iterator j(slotres.begin());  j != slotres.end();  ++j) {
		if (IS_UNSET_SHARE(j->second)) {
			slotres_map_t::const_iterator f(m_attr->machres().find(j->first));
			// it shouldn't be possible to get here with keys in slotres that aren't in machres
			// but if it should happen it's a benign error, just allocate 0 of the unknown resource.
			double avail = (f != m_attr->machres().end()) ? f->second : 0;
			j->second = compute_local_resource(avail, default_share);
		}
	}

		// Now create the object.
	return new CpuAttributes( m_attr, type, cpus, ram, swap_fraction, disk_fraction, slotres, execute_dir, partition_id );
}