Exemplo n.º 1
0
static int _fill_base_msg(entry_list_t *elist,
                          mc_msg_t* base,
                          _parse_info_t* parse_info) {
  FBI_ASSERT(elist && base && parse_info);
  uint64_t i;
  int numDoubles = 0;
  parse_info->reqid = 0;
  parse_info->key_idx = -1;
  parse_info->value_idx = -1;

#ifndef LIBMC_FBTRACE_DISABLE

  parse_info->fbtrace_idx = -1;

#endif

  parse_info->stats_count = 0;
  uint64_t field_mask = 0;

  for (i = 0; i < elist->nentries; i++) {
    uint16_t tag = ntoh16(elist->entries[i].tag);
    uint64_t val = ntoh64(elist->entries[i].data.val);

    // No dup fields (except for stats and double)
    if ((tag & field_mask) && (tag != msg_stats && tag != msg_double)) {
      dbg_error("Duplicate field: field_mask = 0x%lX, field = 0x%X\n",
                field_mask, tag);
      return -1;
    }
    field_mask |= tag;
    switch (tag) {
      case msg_op:
        if (val >= UM_NOPS) {
          return -1;
        }
        base->op = umbrella_op_to_mc[val];
        if (base->op == mc_nops) {
          return -1;
        }
        break;
      case msg_result:
        if (val >= mc_nres) {
          return -1;
        }
        base->result = umbrella_res_to_mc[val];
        break;
      case msg_reqid:
        if (val == 0) {
          return -1;
        }
        parse_info->reqid = val;
        break;
      case msg_err_code:
        base->err_code = val;
        break;
      case msg_flags:
        base->flags = val;
        break;
      case msg_exptime:
        base->exptime = val;
        break;
      case msg_number:
        base->number = val;
        break;
      case msg_delta:
        base->delta = val;
        break;
      case msg_lease_id:
        base->lease_id = val;
        break;
      case msg_cas:
        base->cas = val;
        break;
      case msg_double:
        if (numDoubles == 0 ) {
          memcpy(&base->lowval, &val, sizeof(double));
        } else if (numDoubles == 1) {
          memcpy(&base->highval, &val, sizeof(double));
        } else {
          return -1;
        }
        numDoubles++;
        break;
      case msg_key:
        if (parse_info->key_idx == -1) {
          parse_info->key_idx = i;
        }
        break;
      case msg_value:
        if (parse_info->value_idx != -1) {
          return -1;
        }
        parse_info->value_idx = i;
        break;
      case msg_stats:
        parse_info->stats_count++;
        break;

#ifndef LIBMC_FBTRACE_DISABLE

      case msg_fbtrace:
        if (parse_info->fbtrace_idx != -1) {
          return -1;
        }
        parse_info->fbtrace_idx = i;
        break;

#endif

      default:
        return -1;
    }
  }

  if (parse_info->reqid == 0) {
    return -1;
  }
  if (parse_info->key_idx >= (int64_t)elist->nentries) {
    return -1;
  }
  if (parse_info->value_idx >= (int64_t)elist->nentries) {
    return -1;
  }

  if (!valid_msg(base->op, field_mask)) {
    dbg_error("Invalid message");
    return -1;
  }

  return 0;
}
Exemplo n.º 2
0
/*
 * __gtxt(catname, id, dflt): Return a pointer to a message.
 *	catname is the name of the catalog. If null, the default catalog is
 *		used.
 *	id is the numeric id of the message in the catalogue
 *	dflt is the default message.
 *
 *	Information about non-existent catalogues is kept in db_info, in
 *	such a way that subsequent calls with the same catalogue do not
 *	try to open the catalogue again.
 */
const char *
__gtxt(const char *catname, int id, const char *dflt)
{
	char	*curloc;
	struct db_info *db;
	int	err;

	/* Check for invalid message id */
	if (id < 0)
		return (not_found);
	if (id == 0)
		return ((dflt && *dflt) ? dflt : not_found);

	/*
	 * If catalogue is unspecified, use default catalogue.
	 * No catalogue at all is an error
	 */
	if (!catname || !*catname) {
		lrw_rdlock(&_rw_cur_cat);
		if (cur_cat == NULL || !*cur_cat) {
			lrw_unlock(&_rw_cur_cat);
			return (not_found);
		}
		catname = cur_cat;
		lrw_unlock(&_rw_cur_cat);
	}

	curloc = setlocale(LC_MESSAGES, NULL);

	/* First look up the cache */
	db = lookup_cache(NULL, curloc, catname);
	if (db != NULL) {
		/*
		 * The catalog has been loaded, and if id seems valid,
		 * then just return.
		 */
		if (valid_msg(db, id))
			return (msg(db, id));

		/*
		 * seems given id is out of bound or does not exist. In this
		 * case, we need to look up a message for the "C" locale as
		 * documented in the man page.
		 */
		db = lookup_cache(NULL, def_locale, catname);
		if (db == NULL) {
			/*
			 * Even the message catalog for the "C" has not been
			 * loaded.
			 */
			db = load_db(def_locale, catname, &err);
			if (err)
				return (not_found);
		}
		if (valid_msg(db, id))
			return (msg(db, id));
		/* no message found */
		return ((dflt && *dflt) ? dflt : not_found);
	}

	/*
	 * The catalog has not been loaded or even has not
	 * attempted to be loaded, invalidate all caches related to
	 * the catname for possibly different locale.
	 */
	db = NULL;
	while ((db = lookup_cache(db, NULL, catname)) != NULL)
		unload_db(db);

	/*
	 * load a message catalog for the requested locale.
	 */
	db = load_db(curloc, catname, &err);
	if (err)
		return (not_found);
	if (valid_msg(db, id))
		return (msg(db, id));

	/*
	 * If the requested catalog is either not exist or message
	 * id is invalid, then try to load from "C" locale.
	 */
	db = load_db(def_locale, catname, &err);
	if (err)
		return (not_found);

	if (valid_msg(db, id))
		return (msg(db, id));

	/* no message found */
	return ((dflt && *dflt) ? dflt : not_found);
}