示例#1
0
文件: si.c 项目: ychtiger/capiflash
void *si_new(uint64_t nh, uint64_t ne, uint64_t nb) {

  SI *si = am_malloc(sizeof(SI)); 
  if (si == NULL)
  {
    errno = ENOMEM;
    KV_TRC_FFDC(pAT, "FFDC1: nh %ld ne %ld nb %ld, rc = %d",
            nh, ne, nb, errno);
    return NULL;
  }
  
  si->nh = nh;
  si->ne = ne;
  si->nb = nb;
  
  si->ent_next = 0;
  si->gid_next = 0;
  si->dat_next = 0;

  si->tbl = am_malloc(nh * sizeof(uint64_t));
  if ( si->tbl == NULL )
  {
    errno = ENOMEM;
    KV_TRC_FFDC(pAT, "FFDC2: nh %ld ne %ld nb %ld, rc = %d",
            nh, ne, nb, errno);
  }
  else
  {
    memset(si->tbl, 0xFF, nh * sizeof(uint64_t));
    si->dat = am_malloc(nb);
    if (si->dat == NULL)
    {
      errno = ENOMEM;
      KV_TRC_FFDC(pAT, "FFDC3: nh %ld ne %ld nb %ld, rc = %d",
              nh, ne, nb, errno);
      am_free(si->tbl);
      am_free(si);
      si = NULL;
    }
    else
    {
      si->ent = am_malloc(ne * sizeof(SIE));
      if (si->ent == NULL)
      {
        errno = ENOMEM;
        KV_TRC_FFDC(pAT, "FFDC4: nh %ld ne %ld nb %ld, rc = %d",
                nh, ne, nb, errno);
        am_free(si->tbl);
        am_free(si->dat);
        am_free(si);
        si = NULL;
      }
    }
  }

  memset(si->tbl, 0xFF, nh * sizeof(uint64_t));
  return si;
}
示例#2
0
文件: json.c 项目: deflomu/Automatic
/** \brief Create a Transmission-specific JSON packet in order to add a new download
 * to Transmission.
 *
 * \param[in] data Pointer to the torrent data
 * \param[in] tsize size of the torrent data
 * \param[in] start Determines if the torrent shall start to download right away or be added in a paused state
 * \param[in] folder Optional parameter to set the download folder for this torrent
 * \param[out] setme_size size of the resulting JSON packet
 * \return pointer to the JSON string
 *
 * The function Base64-encodes the given torrent content and encapsulates it in a JSON packet.
 * The packet can then be sent to Transmission via HTTP POST.
 */
char* makeTorrentAddMetaInfoJSON(const void *data, uint32_t tsize, uint8_t start, const char* folder, uint32_t *setme_size) {

	char *encoded = NULL;

	char *buf = NULL;
   char *folder_str = NULL;
	int buf_size, json_size, folderstr_size = 0;
	uint32_t enc_size;
	const char *JSONstr =
		"{\n"
		"\"method\": \"torrent-add\",\n"
		"\"arguments\": {\n"
		"\"metainfo\": \"%s\",\n"
      "%s"
      "\"paused\": %d\n"
		"}\n"
		"}";

  *setme_size = 0;

  encoded = base64_encode((const char*)data, tsize, &enc_size);

  if(encoded && enc_size > 0) {
    if(folder && *folder) {
      folderstr_size = strlen(folder) + 20;
      folder_str = (char*)am_malloc(folderstr_size);
      assert(folder_str && "am_malloc(folder_str) failed!");
      snprintf(folder_str, folderstr_size, "\"download-dir\": \"%s\",\n", folder);
      dbg_printf(P_INFO, "folder_str: %s", folder_str);
    }

    buf_size = enc_size + strlen(JSONstr) + folderstr_size + 10;
    buf = (char*)am_malloc(buf_size);
    memset(buf, 0, buf_size);
    json_size = snprintf(buf, buf_size, JSONstr, encoded, folder_str ? folder_str : "", start ? 0 : 1);
    if(json_size < 0 || json_size >= buf_size) {
      dbg_printf(P_ERROR, "Error producing JSON string with Base64-encoded metadata: %s", strerror(errno));
      am_free(encoded);
      am_free(buf);
      return NULL;
    }

    buf[json_size] = '\0';
    dbg_printf(P_INFO2, "JSON: %s", buf);
    if(setme_size) {
      *setme_size = json_size;
    }
    am_free(folder_str);
    am_free(encoded);
    return buf;
  }
  return NULL;
}
示例#3
0
文件: web.c 项目: deflomu/Automatic
PRIVATE size_t write_data_callback(void *ptr, size_t size, size_t nmemb, void *data) {
  size_t line_len = size * nmemb;
  WebData *mem = data;

  /**
   * if content-length detection in write_header_callback was not successful, mem->response->data will be NULL
   * as a fallback, allocate a predefined size of memory and realloc if necessary
  **/
  if(!mem->response->data) {
    mem->response->buffer_size = DATA_BUFFER_SIZE;
    mem->response->data = (char*)am_malloc(mem->response->buffer_size);
    dbg_printf(P_INFO2, "[write_data_callback] allocated %d bytes for mem->response->data", mem->response->buffer_size);
  }

  if(mem->response->buffer_pos + line_len + 1 > mem->response->buffer_size) {
   do {
      mem->response->buffer_size *= 2;
   }while(mem->response->buffer_size < mem->response->buffer_pos + line_len + 1);

   mem->response->data = (char *)am_realloc(mem->response->data, mem->response->buffer_size);
  }

  if(mem->response->data) {
    memcpy(&(mem->response->data[mem->response->buffer_pos]), ptr, line_len);
    mem->response->buffer_pos += line_len;
    mem->response->data[mem->response->buffer_pos] = 0;
  }

  return line_len;
}
示例#4
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
IV *iv_new(uint64_t n, uint64_t m) {

  uint64_t bits  = n * m;
  uint64_t words = divup(bits, 64);
  uint64_t bytes = sizeof(IV) + words * sizeof(uint64_t);

  IV *iv = am_malloc(bytes);
  if (iv == NULL)
  {
    errno = ENOMEM;
    KV_TRC_FFDC(pAT, "FFDC: n %"PRIu64" m %"PRIu64", errno = %d", n, m, errno);
  }
  else
  {
    memset(iv,0x00, bytes);
    iv->n      =  n;
    iv->m      = m;
    iv->bits   = bits;
    iv->words  = words;
    iv->mask   = 1;
    iv->mask <<= m;
    iv->mask  -= 1;
    iv->bar    = 64 - m;
  }
  KV_TRC(pAT, "iv:%p n:%ld m:%ld", iv, n, m);
  return iv;
}
示例#5
0
auto_handle* session_init(void) {
  char path[MAXPATHLEN];
  char *home;

  auto_handle *ses = am_malloc(sizeof(auto_handle));

  /* numbers */
  ses->max_bucket_items     = AM_DEFAULT_MAXBUCKET;
  ses->bucket_changed       = 0;
  ses->check_interval       = AM_DEFAULT_INTERVAL;

  /* strings */
  ses->download_folder        = get_temp_folder();
  home = get_home_folder();
  sprintf(path, "%s/%s", home, AM_DEFAULT_STATEFILE);
  am_free(home);
  ses->statefile             = am_strdup(path);
  ses->prowl_key             = NULL;
  ses->prowl_key_valid       = 0;
  ses->download_done_script  = NULL;
  ses->match_only            = 0;

  /* lists */
  ses->filters               = NULL;
  ses->feeds                 = NULL;
  ses->downloads             = NULL;

  return ses;
}
示例#6
0
文件: prowl.c 项目: cjo9900/Automatic
static char* createProwlMessage(const char* apikey, const char* event, const char* desc, int32_t *size) {
  int32_t result, apikey_length, event_length, desc_length, total_size;

  char *msg = NULL;

  *size = 0;

  if(!apikey) {
    dbg_printf(P_ERROR, "[createProwlMessage] apikey == NULL");
    *size = 0;
    return NULL;
  }

  if((!event && !desc)) {
    dbg_printf(P_ERROR, "[createProwlMessage] event == NULL && desc == NULL");
    *size = 0;
    return NULL;
  }

  apikey_length = strlen(apikey);
  event_length  = event ? strlen(event) : 0;
  desc_length   = desc  ? strlen(desc)  : 0;

  total_size = apikey_length + event_length + desc_length + 80;
  msg = (char*)am_malloc(total_size);

  if(msg) {
    result = snprintf(msg, total_size, "apikey=%s&priority=0&application=Automatic&event=%s&description=%s",
        apikey, event, desc);
    *size = result;
  }
  return msg;
}
示例#7
0
kvp_t *
kvp_new (void){
	kvp_t *k;
	k = am_malloc (sizeof (kvp_t));
	k->key = NULL;
	k->value = NULL;
	return k;
}
示例#8
0
/** \brief Create a new RSS feed node
 *
 * \return Pointer to the new feed node
 */
PUBLIC rss_feed* feed_new(void) {
	rss_feed* i = (rss_feed*)am_malloc(sizeof(struct rss_feed));
	if(i != NULL) {
		i->url  = NULL;
		i->cookies = NULL;
		i->ttl = -1;
	}
	return i;
}
示例#9
0
文件: json.c 项目: deflomu/Automatic
char* makeChangeUpSpeedJSON(torrent_id_t tID, uint32_t upspeed, uint8_t rpcVersion, uint32_t *setme_size) {
  char *buf = NULL;
  int buf_size, json_size = 0;
  const char *JSONstr =
     "{\n"
     "\"method\": \"torrent-set\",\n"
     "\"arguments\": {\n"
     "\"ids\": %d,\n"
     "\"%s\": %d,\n"
     "\"%s\": true\n"
     "}\n"
     "}";

  *setme_size = 0;

  if(rpcVersion <= 0) {
    dbg_printf(P_ERROR, "Invalid RPC version: %d", rpcVersion);
    return NULL;
  }

  if(upspeed <= 0) {
    dbg_printf(P_ERROR, "Invalid upspeed value: %d", upspeed);
    return NULL;
  }

  if(tID <= 0) {
    dbg_printf(P_ERROR, "Invalid torrent ID: %d", tID);
    return NULL;
  }

  buf_size = strlen(JSONstr) + 60;
  buf = am_malloc(buf_size);
  if(!buf) {
    dbg_printf(P_DBG, "Mem alloc for JSON string failed!");
    return NULL;
  }
  memset(buf, 0, buf_size);

  if(rpcVersion <= 4) {
    json_size = snprintf(buf, buf_size, JSONstr, tID, "speed-limit-up", upspeed, "speed-limit-up-enabled");
  } else if(rpcVersion >= 5 ) {
    json_size = snprintf(buf, buf_size, JSONstr, tID, "uploadLimit", upspeed, "uploadLimited");
  }

  if(json_size < 0 || json_size >= buf_size) {
    dbg_printf(P_ERROR, "Error producing JSON string with Base64-encoded metadata: %s", strerror(errno));
    am_free(buf);
    return NULL;
  }
  buf[json_size] = '\0';

  if(setme_size) {
    *setme_size = json_size;
  }

  return buf;
}
示例#10
0
/**
 * Create a list of expandable variables from envp and possibly argv
 */
am_list_t *
create_expandable_variable_list (MYSQL *mysql, const char *envp[], const char *argv[]){
	time_t t;
	char      *escaped_username = NULL;
	char      *escaped_password = NULL;
	const char *username, *password;
	am_list_t *l = am_list_new ();

	if (l == NULL)
		return l;

	t = time (NULL);

	username = get_env ("username", envp);
	password = get_env ("password", envp);
	if (username != NULL){
		escaped_username = (char *) am_malloc (sizeof(char) * (strlen (username) * 2 + 1));
		mysql_real_escape_string (mysql, escaped_username, username, strlen (username));
	}
	if (password != NULL){
		escaped_password = (char *) am_malloc (sizeof(char) * (strlen (password) * 2 + 1));
		mysql_real_escape_string (mysql, escaped_password, password, strlen (password));
	}

	am_list_append (l, kvp_new_with_kv (EV_DUP ("time_now"), strdupf ("%d", t)));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("username"), NULL_OR_DUP (username)));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("password"), NULL_OR_DUP (password)));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("escaped_username"), NULL_OR_DUP (escaped_username)));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("escaped_password"), NULL_OR_DUP (escaped_password)));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("trusted_port"), NULL_OR_DUP (get_env ("trusted_port", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("trusted_ip"), NULL_OR_DUP (get_env ("trusted_ip", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("time_unix"), NULL_OR_DUP (get_env ("time_unix", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("ifconfig_pool_remote_ip"), NULL_OR_DUP (get_env ("ifconfig_pool_remote_ip", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("ifconfig_pool_local_ip"), NULL_OR_DUP (get_env ("ifconfig_pool_local_ip", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("ifconfig_local"), NULL_OR_DUP (get_env ("ifconfig_local", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("time_duration"), NULL_OR_DUP (get_env ("time_duration", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("bytes_sent"), NULL_OR_DUP (get_env ("bytes_sent", envp))));
	am_list_append (l, kvp_new_with_kv (EV_DUP ("bytes_received"), NULL_OR_DUP (get_env ("bytes_received", envp))));

	am_free (escaped_username);
	am_free (escaped_password);
  return l;
}
示例#11
0
文件: web.c 项目: deflomu/Automatic
PRIVATE HTTPResponse* HTTPResponse_new(void) {
  HTTPResponse* resp = (HTTPResponse*)am_malloc(sizeof(struct HTTPResponse));
  if(resp) {
    resp->size = 0;
    resp->responseCode = 0;
    resp->data = NULL;
    resp->content_filename = NULL;
  }
  return resp;
}
示例#12
0
queue_t *queue_new(uint32_t n) {
  queue_t *q = am_malloc(sizeof(queue_t) + n * sizeof(int32_t));
  q->n = n;
  q->c = 0;
  q->h = 0;
  q->t = 0;
  q->waiters = 0;
  pthread_mutex_init(&q->m,NULL);
  pthread_cond_init(&q->cond,NULL);
  return q;
}
示例#13
0
文件: web.c 项目: deflomu/Automatic
PRIVATE struct HTTPData* HTTPData_new(void) {
  HTTPData* data = NULL;

  data = am_malloc(sizeof(struct HTTPData));
  if(!data) {
    return NULL;
  }

  data->data = NULL;
  data->buffer_size = 0;
  data->buffer_pos = 0;
  return data;
}
示例#14
0
PRIVATE char* shorten(const char *str) {

  int tmp_pos;
  char c;
  char *retStr;
  char *tmp = (char*)am_malloc(MAX_PARAM_LEN+1);
  uint32_t line_pos = 0, i;
  uint32_t len = strlen(str);

  if(!tmp) {
    dbg_printf(P_ERROR, "[shorten] calloc(MAX_PARAM_LEN) failed!");
    return NULL;
  }

  memset(tmp, 0, MAX_PARAM_LEN+1);

  while (isspace(str[line_pos])) {
    ++line_pos;
  }
  tmp_pos = 0;
  while(line_pos < len) {
    /* case 1: quoted strings */
    if(tmp_pos != 0) {
      for(i = 0; i < strlen(AM_DELIMITER); ++i)
        tmp[tmp_pos++] = AM_DELIMITER[i];
    }
    if (str[line_pos] == '"' || str[line_pos] == '\'') {
      c = str[line_pos];
      ++line_pos;  /* skip quote */
      while(str[line_pos] != c && line_pos < len && str[line_pos] != '\n' && str[line_pos] != '\0') {
        tmp[tmp_pos++] = str[line_pos++];
      }
      if(str[line_pos] == c) {
        line_pos++; /* skip the closing quote */
      }
    } else {
      while(line_pos < len && str[line_pos] != '\n' && str[line_pos] != '\0') {
        tmp[tmp_pos++] = str[line_pos++];
      }
    }
    while (isspace(str[line_pos])) {
      ++line_pos;
    }
  }
  tmp[tmp_pos] = '\0';
  assert(strlen(tmp) < MAX_PARAM_LEN);
  retStr = am_strdup(tmp);
  am_free(tmp);
  return retStr;
}
示例#15
0
int addToTail(void* elem, NODE **head) {
	NODE *newnode = NULL;

	if(head != NULL && elem != NULL) {
		newnode = (NODE*)am_malloc(sizeof(struct NODE));

		if(newnode != NULL) {
			newnode->data = elem;
			newnode->next = NULL;
			addNodeLast(head, newnode);
			return 0;
		}
		return -1;
	}
	return -1;
}
示例#16
0
auto_handle* session_init(void) {
  char path[MAXPATHLEN];
  char *home;

  am_session_t *ses = am_malloc(sizeof(am_session_t));

  /* numbers */
  ses->rpc_version          = AM_DEFAULT_RPC_VERSION;
  ses->max_bucket_items     = AM_DEFAULT_MAXBUCKET;
  ses->bucket_changed       = 0;
  ses->check_interval       = AM_DEFAULT_INTERVAL;
  ses->use_transmission     = AM_DEFAULT_USETRANSMISSION;
  ses->start_torrent        = AM_DEFAULT_STARTTORRENTS;
  ses->transmission_version = AM_TRANSMISSION_1_3;
  ses->rpc_port             = AM_DEFAULT_RPCPORT;

  /* strings */
  ses->transmission_path     = get_tr_folder();
  ses->torrent_folder        = get_temp_folder();
  ses->host                  = NULL;
  ses->auth                  = NULL;
  home = get_home_folder();
  sprintf(path, "%s/%s", home, AM_DEFAULT_STATEFILE);
  am_free(home);
  ses->statefile             = am_strdup(path);
  ses->prowl_key             = NULL;
  ses->toasty_key            = NULL;
  ses->pushalot_key          = NULL;
  ses->pushover_key          = NULL;
  ses->prowl_key_valid       = 0;
  ses->match_only            = 0;
  ses->transmission_external = NULL;

  /* lists */
  ses->filters              = NULL;
  ses->feeds                 = NULL;
  ses->downloads             = NULL;
  ses->upspeed               = -1;

  return ses;
}
示例#17
0
PRIVATE suboption_t* parseSubOption(char* line) {
  const char *subopt_delim = "=>";
  uint32_t i = 0;

  suboption_t* option_item = NULL;
  char *option = NULL;
  char *param  = NULL;

  assert(line && *line);

  while(line[i] != '\0') {
    if(line[i] == subopt_delim[0] && line[i+1] == subopt_delim[1]) {
      if(i >1) {
        option = am_strndup(line, i-1);
        param  = trim(line + i + strlen(subopt_delim));
      } else {
        dbg_printf(P_ERROR, "Error: Suboption '%s' is malformed!", line);
      }

      break;
    }

    i++;
  }

  if(option && param) {
    option_item = (suboption_t*)am_malloc(sizeof(suboption_t));
    option_item->option = option;
    option_item->value = param;
  }

  if(!option_item) {
    dbg_printf(P_ERROR, "Error parsing suboption from input string '%s')", line);
    am_free(option);
    am_free(param);
  }

  return option_item;
}
示例#18
0
文件: web.c 项目: deflomu/Automatic
/** \brief Create a new WebData object
*
* \param[in] url URL for a WebData object
*
* The parameter \a url is optional. You may provide \c NULL if no URL is required or not known yet.
*/
PRIVATE struct WebData* WebData_new(const char *url) {
  WebData *data = NULL;

  data = am_malloc(sizeof(WebData));
  if(!data)
    return NULL;

  data->url = NULL;
  data->content_filename = NULL;
  data->content_length = -1;
  data->response = NULL;

  if(url) {
    data->url = am_strdup((char*)url);
  }

  data->response = HTTPData_new();
  if(!data->response) {
    WebData_free(data);
    return NULL;
  }
  return data;
}
示例#19
0
/**
 * handle the actual query of _am_mysql_handle_pf_rules_single_query
 * given the query to execute
 */
int
_am_mysql_handle_pf_rules_do_single_query (
    MYSQL                 *mysql,
    char                  *query,
    am_list_t             *expandable_vars,
    struct pf_rules *pf_rules)
{
  MYSQL_RES			*result = NULL;
  MYSQL_ROW     row;
  unsigned long *lengths;
  int rc = 0;
  my_ulonglong  num_rows;
  char *fmt_query = NULL;

  if (query == NULL)
    return -1;

  fmt_query = expand_query (query, expandable_vars);

  if (fmt_query == NULL){
    LOGERROR ("Could not set expandable variables in _am_mysql_handle_default_pf_rules_query\n");
    return -1;
  }

	/* Now for the query itself */
	if (mysql_query(mysql, fmt_query))
	{
		/* query failed */
		rc = -1;
		LOGERROR ("_am_mysql_handle_default_pf_rules_query: Failed to execute query: Error (%d): %s\n", mysql_errno(mysql), mysql_error(mysql));
		goto _handle_pf_rules_do_single_query;
	}

	if ((result = mysql_store_result(mysql)) == NULL)
	{
		/*
		* Failed to get result
		* 2 cases:
		*		- no result expected (after an insert statement...
		*		- error getting result
		*/
		if (mysql_field_count (mysql) == 0){
			/* insert like statement, should not happen!; */
			rc = -1;
			goto _handle_pf_rules_do_single_query;
		}else{
			rc = -1;
			LOGERROR ("_am_mysql_handle_default_pf_rules_query: Failed to store query results: Error (%d): %s\n", mysql_errno(mysql), mysql_error(mysql));
			goto _handle_pf_rules_do_single_query;
		}
	}
  num_rows = mysql_num_rows(result);
	/* If num_rows > 1, we consider it is an error */
	if (num_rows > 1 ){
    rc = -1;
    LOGERROR ("_am_mysql_handle_default_pf_rules_query: Many results were found while only 1 was expected!\n");
    goto _handle_pf_rules_do_single_query;
  }
  if (num_rows == 0){
    /* no result found */
    rc = 0;
    goto _handle_pf_rules_do_single_query;
  }
  /* If we dont have 4 fields, we should fail too */
  if (mysql_num_fields(result) != 4 ){
    rc = -1;
    LOGERROR ("_am_mysql_handle_default_pf_rules_query: MySQL result do not contain exactly 4 fields!\n");
    goto _handle_pf_rules_do_single_query;
  }

  row = mysql_fetch_row(result);
  if (row == NULL){
    /* An error occurred */
    rc = -1;
    LOGERROR ("_am_mysql_handle_default_pf_rules_query: Failed to return first row, Error (%d): %s\n", mysql_errno(mysql), mysql_error(mysql));
    goto _handle_pf_rules_do_single_query;
  }
  lengths = mysql_fetch_lengths(result);
  /* no we set the values */
  rc = 1;
  /* default rules */
  pf_rules->default_pf_rules_clients = pf_default_drop_or_accept (row[0]);
  pf_rules->default_pf_rules_subnets = pf_default_drop_or_accept (row[1]);
  /* clients rules */
  if ( lengths[2] != 0 ){
    pf_rules->pf_rules_clients = am_malloc (lengths[2] + 1);
    if (pf_rules->pf_rules_clients == NULL){
      LOGERROR ("Could not allocate memory for pf_rules_clients\n");
    }else{
      memcpy (pf_rules->pf_rules_clients, row[2], lengths[2]);
      pf_rules->pf_rules_clients[lengths[2]] = '\0';
    }
  }else{
    pf_rules->pf_rules_clients = NULL;
  }
  /* subnets rules */
  if ( lengths[3] != 0 ){
    pf_rules->pf_rules_subnets = am_malloc (lengths[3] + 1);
    if (pf_rules->pf_rules_subnets == NULL){
      LOGERROR ("Could not allocate memory for pf_rules_subnets\n");
    }else{
      memcpy (pf_rules->pf_rules_subnets, row[3], lengths[3]);
      pf_rules->pf_rules_subnets[lengths[3]] = '\0';
    }
  }else{
    pf_rules->pf_rules_subnets = NULL;
  }
_handle_pf_rules_do_single_query:
  if (result != NULL)
    mysql_free_result (result);
  if (fmt_query != NULL)
    am_free (fmt_query);
  return rc;
}
示例#20
0
/** \brief parse configuration file.
*
* \param[in,out] as Pointer to session handle
* \param[in] filename Path to the configuration file
* \return 0 if parsing was successful, -1 if an error occured.
*/
int parse_config_file(struct auto_handle *as, const char *filename) {
  FILE *fp = NULL;
  char *line = NULL;
  char opt[MAX_OPT_LEN + 1];
  char *param = NULL;
  char erbuf[100];
  char c;		/* for the "" and '' check */
  int line_num = 0;
  int line_pos;	/* line pos */
  int opt_pos;	/* opt pos */
  int param_pos;	/* param pos */
  int parse_error = 0;
  int opt_good = 0;
  int param_good = 0;
  struct stat fs;
  option_type type;

  if(stat(filename, &fs) == -1)  {
    return -1;
  }
  dbg_printf(P_INFO2, "Configuration file size: %d", fs.st_size);

  if ((fp = fopen(filename, "rb")) == NULL) {
    perror("fopen");
    return -1;
  }

  if ((line = am_malloc(fs.st_size + 1)) == NULL) {
    dbg_printf(P_ERROR, "Can't allocate memory for 'line': %s (%ldb)", strerror(errno), fs.st_size + 1);
    return -1;
  }

  if(fread(line, fs.st_size, 1, fp) != 1) {
    perror("fread");
    fclose(fp);
    am_free(line);
    return -1;
  }
  if(fp) {
    fclose(fp);
  }
  line_pos = 0;

  param = (char*)am_malloc(MAX_PARAM_LEN + 1);
  if(!param) {
    dbg_printf(P_ERROR, "Can't allocate memory for 'param': %s (%ldb)", strerror(errno), MAX_PARAM_LEN + 1);
    am_free(line);
    return -1;
  }

  while(line_pos != fs.st_size) {
    /* skip whitespaces */
    while (isspace(line[line_pos])) {
      if(line[line_pos] == '\n') {
        dbg_printf(P_INFO2, "skipping newline (line %d)", line_num);
        line_num++;
      }
      ++line_pos;
    }

    if(line_pos >= fs.st_size) {
      break;
    }

    /* comment */
    if (line[line_pos] == '#') {
      dbg_printf(P_INFO2, "skipping comment (line %d)", line_num);
      while (line[line_pos] != '\n') {
        ++line_pos;
      }
      ++line_num;
      ++line_pos;  /* skip the newline as well */
      continue;
    }

    /* read option */
    for (opt_pos = 0; isprint(line[line_pos]) && line[line_pos] != ' ' &&
      line[line_pos] != '#' && line[line_pos] != '='; /* NOTHING */) {
        opt[opt_pos++] = line[line_pos++];
        if (opt_pos >= MAX_OPT_LEN) {
          dbg_printf(P_ERROR, "too long option at line %d", line_num);
          parse_error = 1;
          opt_good = 0;
        }
    }
    if (opt_pos == 0 || parse_error == 1) {
      dbg_printf(P_ERROR, "parse error at line %d (pos: %d)", line_num, line_pos);
      parse_error = 1;
      break;
    } else {
      opt[opt_pos] = '\0';
      opt_good = 1;
    }
    /* skip whitespaces */
    while (isspace(line[line_pos])) {
      if(line[line_pos] == '\n') {
        line_num++;
        dbg_printf(P_INFO2, "skipping newline (line %d)", line_num);
      }
      ++line_pos;
    }

    if(line_pos >= fs.st_size) {
      break;
    }

    /* check for '=' */
    if (line[line_pos++] != '=') {
      snprintf(erbuf, sizeof(erbuf), "Option '%s' needs a parameter (line %d)", opt, line_num);
      parse_error = 1;
      break;
    }

    /* skip whitespaces */
    while (isspace(line[line_pos])) {
      if(line[line_pos] == '\n') {
        line_num++;
        dbg_printf(P_INFO2, "skipping newline (line %d)", line_num);
      }
      ++line_pos;
    }

    if(line_pos >= fs.st_size) {
      break;
    }

    /* read the parameter */

    /* case 1: single string, no linebreaks allowed */
    if (line[line_pos] == '"' || line[line_pos] == '\'') {
      c = line[line_pos]; /* single or double quote */
      ++line_pos;  /* skip quote */
      parse_error = 0;
      for (param_pos = 0; line[line_pos] != c; /* NOTHING */) {
        if(line_pos < fs.st_size && param_pos < MAX_PARAM_LEN && line[line_pos] != '\n') {
          param[param_pos++] = line[line_pos++];
        } else {
          snprintf(erbuf, sizeof(erbuf), "Option %s has a too long parameter (line %d)\n",opt, line_num);
          parse_error = 1;
          break;
        }
      }
      if(parse_error == 0) {
        line_pos++;	/* skip the closing " or ' */
        type = CONF_TYPE_STRING;
      } else {
        break;
      }
      /* case 2: multiple items, linebreaks allowed */
    } else if (line[line_pos] == '{') {
      dbg_printf(P_INFO2, "reading multiline param", line_num);
      ++line_pos;
      parse_error = 0;
      for (param_pos = 0; line[line_pos] != '}'; /* NOTHING */) {
        if(line_pos < fs.st_size && param_pos < MAX_PARAM_LEN) {
          param[param_pos++] = line[line_pos++];
          if(line[line_pos] == '\n')
            line_num++;
        } else {
          snprintf(erbuf, sizeof(erbuf), "Option %s has a too long parameter (line %d)\n", opt, line_num);
          parse_error = 1;
          break;
        }
      }
      dbg_printf(P_INFO2, "multiline param: param_good=%d", param_good);
      if(parse_error == 0) {
        line_pos++;	/* skip the closing '}' */
        type = CONF_TYPE_STRINGLIST;
      } else {
        break;
      }
      /* Case 3: integers */
    } else {
      parse_error = 0;
      for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos])
        && line[line_pos] != '#'; /* NOTHING */) {
          param[param_pos++] = line[line_pos++];
          if (param_pos >= MAX_PARAM_LEN) {
            snprintf(erbuf, sizeof(erbuf), "Option %s has a too long parameter (line %d)\n", opt, line_num);
            parse_error = 1;
            break;
          }
      }
      if(parse_error == 0) {
        type = CONF_TYPE_INT;
      } else {
        break;
      }
    }
    param[param_pos] = '\0';
    dbg_printf(P_INFO2, "[parse_config_file] option: %s", opt);
    dbg_printf(P_INFO2, "[parse_config_file] param: %s (%d byte)", param, strlen(param));
    dbg_printf(P_INFO2, "[parse_config_file] -----------------");
    set_option(as, opt, param, type);

    /* skip whitespaces */
    while (isspace(line[line_pos])) {
      if(line[line_pos] == '\n')
        line_num++;
      ++line_pos;
    }
    if(line_pos >= fs.st_size) {
      break;
    }
  }

  am_free(line);
  am_free(param);

  return (parse_error == 1) ? -1 : 0;
}
示例#21
0
文件: hash.c 项目: ychtiger/capiflash
hash_t *hash_new(uint64_t n) {
  hash_t *hash = am_malloc(sizeof(hash_t) + n * sizeof(uint64_t));
  bzero(hash, sizeof(hash_t) + n * sizeof(uint64_t));
  hash->n = n;
  return hash;
}
示例#22
0
PRIVATE simple_list parseMultiOption(const char *str) {
  int tmp_pos;
  uint32_t line_pos = 0;
  uint32_t len = strlen(str);
  simple_list options = NULL;
  char tmp[MAX_PARAM_LEN];
  int last_dbl_quote_pos;
  int8_t parse_error = 0;
  int32_t current_line_pos = -1;
  
  if(len == 0) {
    dbg_printf(P_ERROR, "[parseMultiOption] empty input string!");
    return NULL;
  }
  
   while(line_pos < len) {
    memset(&tmp, 0, sizeof(tmp));
    // Skip any initial whitespace
    while (line_pos < len && isspace(str[line_pos])) {
      ++line_pos;
    }
  
    tmp_pos = 0;
    parse_error = 0;
    last_dbl_quote_pos = -1;
    
    while(line_pos < len && str[line_pos] != '\0') {
      if(str[line_pos] == '\"') {
        last_dbl_quote_pos = tmp_pos;
      } else if(str[line_pos] == '\n') {
        // Text is broken over multiple lines
        if(str[line_pos - 1] == '\\' || str[line_pos - 1] == '+') {
          // skip newline
          line_pos++;
          // skip whitespace at the beginning of the next line
          while (line_pos < len && isspace(str[line_pos])) {
            ++line_pos;
          }

          if(str[line_pos] == '\"' && last_dbl_quote_pos != -1) {
            // Reset the string index to the position of the last double-quote, and properly null-terminate it
            tmp_pos = last_dbl_quote_pos;
            tmp[tmp_pos] = '\0';
            
            // Skip the double-quote on the new line as well
            line_pos++;
          } else {
            tmp[tmp_pos] = '\0';
            dbg_printf(P_ERROR, "[parseMultiOption] Parsing error at line '%s'", &tmp[current_line_pos]);
            parse_error = 1;
            break;
          }
        } else {
          // If the character before the newline is not a backslash ('\'), consider this suboption complete
          break;
        }
        
        current_line_pos = tmp_pos;
      }

      tmp[tmp_pos++] = str[line_pos++];
    }

    if(parse_error) {
      break;
    }

    /* A suboption is finished, end it with a null terminator */
    tmp[tmp_pos] = '\0';

    /* store the line in our list */
    if(tmp_pos != 0) {
      suboption_t* i = (suboption_t*)am_malloc(sizeof(suboption_t));
      
      if(i != NULL) {
        if(parseSubOption(tmp, &i->option, &i->value) == SUCCESS) {
          addItem(i, &options);
        } else {
          dbg_printf(P_ERROR, "Invalid suboption string: '%s'", tmp);
        }
      }
    }
  }

  return options;
}
示例#23
0
/** \brief parse configuration file.
*
* \param[in,out] as Pointer to session handle
* \param[in] filename Path to the configuration file
* \return 0 if parsing was successful, -1 if an error occured.
*/
int parse_config_file(struct auto_handle *as, const char *filename) {
  FILE *fp = NULL;
  char *line = NULL;
  char opt[MAX_OPT_LEN + 1];
  char param[MAX_PARAM_LEN + 1];
  char c; /* for the "" and '' check */
  int line_num = 0;
  int line_pos = 0;
  int opt_pos;
  int param_pos;
  int parse_error = 0;
  struct stat fs;
  option_type type;

  if ((fp = fopen(filename, "rb")) == NULL) {
    perror("fopen");
    return -1;
  }

  if(stat(filename, &fs) == -1) {
    fclose(fp);
    return -1;
  }

  if ((line = am_malloc(fs.st_size + 1)) == NULL) {
    dbg_printf(P_ERROR, "Can't allocate memory for 'line': %s (%ldb)", strerror(errno), fs.st_size + 1);
    fclose(fp);
    return -1;
  }

  if(fread(line, fs.st_size, 1, fp) != 1) {
    perror("fread");
    fclose(fp);
    am_free(line);
    return -1;
  }

  /* NULL-terminate the result */
  line[fs.st_size] = '\0';

  if(fp) {
    fclose(fp);
  }

  while(line_pos != fs.st_size) {
    line_pos = SkipWhitespace(line, line_pos, &line_num);

    if(line_pos < 0) {
      parse_error = 1;
      break;
    }

    if(line_pos >= fs.st_size) {
      break;
    }

    /* comment */
    if (line[line_pos] == '#') {
      ////dbg_printf(P_INFO2, "skipping comment (line %d)", line_num);
      while (line[line_pos] != '\n') {
        ++line_pos;
      }

      ++line_num;
      ++line_pos;  /* skip the newline as well */
      continue;
    }

    /* read option */
    for (opt_pos = 0; isprint(line[line_pos]) && line[line_pos] != ' ' &&
         line[line_pos] != '#' && line[line_pos] != '='; /* NOTHING */) {
      opt[opt_pos++] = line[line_pos++];
      if (opt_pos >= MAX_OPT_LEN) {
        dbg_printf(P_ERROR, "too long option at line %d", line_num);
        parse_error = 1;
      }
    }

    if (opt_pos == 0 || parse_error == 1) {
      dbg_printf(P_ERROR, "parse error at line %d (pos: %d)", line_num, line_pos);
      parse_error = 1;
      break;
    } else {
      opt[opt_pos] = '\0';
    }

    line_pos = SkipWhitespace(line, line_pos, &line_num);

    if(line_pos < 0) {
      parse_error = 1;
      break;
    }

    if(line_pos >= fs.st_size) {
      break;
    }

    /* check for '=' */
    if (line[line_pos++] != '=') {
         dbg_printf(P_ERROR, "Option '%s' needs a parameter (line %d)", opt, line_num);
      parse_error = 1;
      break;
    }

    line_pos = SkipWhitespace(line, line_pos, &line_num);

    if(line_pos < 0) {
      parse_error = 1;
      break;
    }

    if(line_pos >= fs.st_size) {
      break;
    }

    /* read the parameter */

    /* case 1: single string, no linebreaks allowed */
    if (line[line_pos] == '"' || line[line_pos] == '\'') {
      c = line[line_pos]; /* single or double quote */
      ++line_pos;  /* skip quote */
      parse_error = 1;
      for (param_pos = 0; (param_pos < MAX_PARAM_LEN) && (line_pos < fs.st_size) && (line[line_pos] != '\n'); /* NOTHING */) {
        if( line[line_pos] == c) {
          parse_error = 0;
          break;
        }
        param[param_pos++] = line[line_pos++];
      }

      if(parse_error == 0) {
        line_pos++;  /* skip the closing single or double quote */
        type = CONF_TYPE_STRING;
      } else {
        dbg_printf(P_ERROR, "Option '%s' has a too long parameter (line %d). Closing quote missing?", opt, line_num);
        break;
      }
    } else if (line[line_pos] == '{') { /* case 2: multiple items, linebreaks allowed */
      dbg_printf(P_DBG, "reading multiline param", line_num);
      ++line_pos;
      parse_error = 1;

      for (param_pos = 0; (line_pos < fs.st_size) && (param_pos < MAX_PARAM_LEN); /* NOTHING */) {
        if(line[line_pos] == '}') {
          parse_error = 0;
          break;
        }
        param[param_pos++] = line[line_pos++];
        if(line[line_pos] == '\n') {
          line_num++;
        }
      }

      if(parse_error == 0) {
        line_pos++;  /* skip the closing '}' */
        type = CONF_TYPE_STRINGLIST;
      } else {
        dbg_printf(P_ERROR, "Option %s has a too long parameter (line %d). Closing bracket missing?", opt, line_num);
        parse_error = 1;
        break;
      }
    } else { /* Case 3: integers */
      parse_error = 0;
      for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos]) && line[line_pos] != '#'; /* NOTHING */) {
          param[param_pos++] = line[line_pos++];
          if (param_pos >= MAX_PARAM_LEN) {
            dbg_printf(P_ERROR, "Option %s has a too long parameter (line %d)", opt, line_num);
            parse_error = 1;
            break;
          }
      }

      if(parse_error == 0) {
        type = CONF_TYPE_INT;
      } else {
        break;
      }
    }

    param[param_pos] = '\0';
    dbg_printf(P_DBG, "[parse_config_file] option: %s", opt);
    dbg_printf(P_DBG, "[parse_config_file] param: %s (%d byte)", param, strlen(param));
    dbg_printf(P_DBG, "[parse_config_file] -----------------");

    if(set_option(as, opt, param, type) == FAILURE) {
      parse_error = 1;
      break;
    }

    line_pos = SkipWhitespace(line, line_pos, &line_num);

    if(line_pos < 0) {
      parse_error = 1;
      break;
    }

    if(line_pos >= fs.st_size) {
      break;
    }
  }

  am_free(line);

  return (parse_error == 1) ? -1 : 0;
}
示例#24
0
int ark_create_verbose(char *path, ARK **arkret,
                       uint64_t size, uint64_t bsize, uint64_t hcount,
                       int nthrds, int nqueue, int basyncs, uint64_t flags)
{
  int          rc = 0;
  int        p_rc = 0;
  uint64_t bcount = 0;
  uint64_t      x = 0;
  int           i = 0;
  int        tnum = 0;
  int        rnum = 0;
  scb_t     *scbp = NULL;

  KV_TRC_OPEN(pAT, "arkdb");

  if (NULL == arkret)
  {
    KV_TRC_FFDC(pAT, "Incorrect value for ARK control block: rc=EINVAL");
    rc = EINVAL;
    goto ark_create_ark_err;
  }

  if ( (flags & (ARK_KV_PERSIST_LOAD|ARK_KV_PERSIST_STORE)) && 
         (flags & ARK_KV_VIRTUAL_LUN) )
  {
    KV_TRC_FFDC(pAT, "Invalid persistence combination with ARK flags: %016lx",
                flags);
    rc = EINVAL;
    goto ark_create_ark_err;
  }

  if (nthrds <= 0)
  {
      KV_TRC_FFDC(pAT, "invalid nthrds:%d", nthrds);
      rc = EINVAL;
      goto ark_create_ark_err;
  }

  _ARK *ark = am_malloc(sizeof(_ARK));
  if (ark == NULL) {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocating ARK control structure for %ld",
                sizeof(_ARK));
    goto ark_create_ark_err;
  }

  KV_TRC(pAT, "%p path(%s) size %ld bsize %ld hcount %ld "
              "nthrds %d nqueue %d basyncs %d flags:%08lx",
              ark, path, size, bsize, hcount, 
              nthrds, nqueue, basyncs, flags);

  ark->bsize    = bsize;
  ark->rthread  = 0;
  ark->persload = 0;
  ark->nasyncs  = ((nqueue <= 0) ? ARK_MAX_ASYNC_OPS : nqueue);
  ark->basyncs  = basyncs;
  ark->ntasks   = ARK_MAX_TASK_OPS;
  ark->nthrds   = ARK_VERBOSE_NTHRDS_DEF; // hardcode, perf requirement

  // Create the KV storage, whether that will be memory based
  // or flash
  ark->ea = ea_new(path, ark->bsize, basyncs, &size, &bcount,
                    (flags & ARK_KV_VIRTUAL_LUN));
  if (ark->ea == NULL)
  {
    if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
    rc = errno;
    KV_TRC_FFDC(pAT, "KV storage initialization failed: rc/errno:%d", rc);
    goto ark_create_ea_err;
  }

  // Now that the "connection" to the store has been established
  // we need to check to see if data was persisted from a previous
  // instantiation of the KV store.
  p_rc = ark_check_persistence(ark, flags);
  if (p_rc > 0)
  {
    // We ran into an error while trying to read from
    // the store.
    rc = p_rc;
    KV_TRC_FFDC(pAT, "Persistence check failed: %d", rc);
    goto ark_create_persist_err;
  }
  else if (p_rc == -1)
  {
    KV_TRC(pAT, "NO PERSIST LOAD FLAG");
    // There was no persistence data, so we just build off
    // of what was passed into the API.

    ark->size = size;
    ark->bcount = bcount;
    ark->hcount = hcount;
    ark->vlimit = ARK_VERBOSE_VLIMIT_DEF;
    ark->blkbits = ARK_VERBOSE_BLKBITS_DEF;
    ark->grow = ARK_VERBOSE_GROW_DEF;
    ark->rthread = 0;
    ark->flags = flags;
    ark->astart = 0;
    ark->blkused = 1;
    ark->ark_exit = 0;
    ark->nactive = 0;
    ark->pers_stats.kv_cnt = 0;
    ark->pers_stats.blk_cnt = 0;
    ark->pers_stats.byte_cnt = 0;
    ark->pcmd = PT_IDLE;

    // Create the requests and tag control blocks and queues.
    x = ark->hcount / ark->nthrds;
    ark->npart  = x + (ark->hcount % ark->nthrds ? 1 : 0);

    // Create the hash table
    ark->ht = hash_new(ark->hcount);
    if (ark->ht == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Hash initialization failed: %d", rc);
      goto ark_create_ht_err;
    }

    // Create the block list
    ark->bl = bl_new(ark->bcount, ark->blkbits);
    if (ark->bl == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Block list initialization failed: %d", rc);
      goto ark_create_bl_err;
    }
    if (flags & ARK_KV_PERSIST_STORE)
    {
      ark_persistence_calc(ark);
      if (bl_reserve(ark->bl, ark->pers_max_blocks))
          {goto ark_create_bl_err;}
    }
  }
  else
  {
      KV_TRC(pAT, "PERSIST: %p path(%s) size %ld bsize %ld hcount %ld "
                  "nthrds %d nqueue %ld basyncs %d bcount %ld blkbits %ld",
                  ark, path, ark->size, ark->bsize, ark->hcount,
                  ark->nthrds, ark->nasyncs, ark->basyncs,
                  ark->bcount, ark->blkbits);
  }

  rc = pthread_mutex_init(&ark->mainmutex,NULL);
  if (rc != 0)
  {
    KV_TRC_FFDC(pAT, "pthread_mutex_init for main mutex failed: %d", rc);
    goto ark_create_pth_mutex_err;
  }

  ark->rtags = tag_new(ark->nasyncs);
  if ( NULL == ark->rtags )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Tag initialization for requests failed: %d", rc);
    goto ark_create_rtag_err;
  }

  ark->ttags = tag_new(ark->ntasks);
  if ( NULL == ark->ttags )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Tag initialization for tasks failed: %d", rc);
    goto ark_create_ttag_err;
  }

  ark->rcbs = am_malloc(ark->nasyncs * sizeof(rcb_t));
  if ( NULL == ark->rcbs )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for request control blocks", (ark->nasyncs * sizeof(rcb_t)));
    goto ark_create_rcbs_err;
  }

  ark->tcbs = am_malloc(ark->ntasks * sizeof(tcb_t));
  if ( NULL == ark->tcbs )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for task control blocks", (ark->ntasks * sizeof(rcb_t)));
    goto ark_create_tcbs_err;
  }

  ark->iocbs = am_malloc(ark->ntasks * sizeof(iocb_t));
  if ( NULL == ark->iocbs )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for io control blocks", (ark->ntasks * sizeof(iocb_t)));
    goto ark_create_iocbs_err;
  }

  ark->poolthreads = am_malloc(ark->nthrds * sizeof(scb_t));
  if ( NULL == ark->poolthreads )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for server thread control blocks", (ark->nthrds * sizeof(scb_t)));
    goto ark_create_poolthreads_err;
  }

  for ( rnum = 0; rnum < ark->nasyncs ; rnum++ )
  {
    ark->rcbs[rnum].stat = A_NULL;
    pthread_cond_init(&(ark->rcbs[rnum].acond), NULL);
    pthread_mutex_init(&(ark->rcbs[rnum].alock), NULL);
  }

  for ( tnum = 0; tnum < ark->ntasks; tnum++ )
  {
    ark->tcbs[tnum].inb = bt_new(0, ark->vlimit, sizeof(uint64_t), 
                                       &(ark->tcbs[tnum].inblen),
                                       &(ark->tcbs[tnum].inb_orig));
    if (ark->tcbs[tnum].inb == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Bucket allocation for inbuffer failed: %d", rc);
      goto ark_create_taskloop_err;
    }

    ark->tcbs[tnum].oub = bt_new(0, ark->vlimit, sizeof(uint64_t), 
                                       &(ark->tcbs[tnum].oublen),
                                       &(ark->tcbs[tnum].oub_orig));
    if (ark->tcbs[tnum].oub == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Bucket allocation for outbuffer failed: %d", rc);
      goto ark_create_taskloop_err;
    }

    //ark->tcbs[tnum].vbsize = bsize * 1024;
    ark->tcbs[tnum].vbsize = bsize * 256;
    ark->tcbs[tnum].vb_orig = am_malloc(ark->tcbs[tnum].vbsize);
    if (ark->tcbs[tnum].vb_orig == NULL)
    {
      rc = ENOMEM;
      KV_TRC_FFDC(pAT, "Out of memory allocation for %"PRIu64" bytes for variable size buffer", (bsize * 1024));
      goto ark_create_taskloop_err;
    }
    ark->tcbs[tnum].vb = ptr_align(ark->tcbs[tnum].vb_orig);
  }

  *arkret = (void *)ark;

  ark->pts = (PT *)am_malloc(sizeof(PT) * ark->nthrds);
  if ( ark->pts == NULL )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation for %"PRIu64" bytes for server thread data", (sizeof(PT) * ark->nthrds));
    goto ark_create_taskloop_err;
  }

  for (i = 0; i < ark->nthrds; i++) {
    PT *pt = &(ark->pts[i]);
    scbp = &(ark->poolthreads[i]);

    memset(scbp, 0, sizeof(scb_t));

    // Start off the random start point for this thread
    // at -1, to show that it has not been part of a
    // ark_random call.
    scbp->rlast = -1;
    scbp->holds = 0;
    scbp->poolstate = PT_RUN;

    scbp->poolstats.io_cnt = 0;
    scbp->poolstats.ops_cnt = 0;
    scbp->poolstats.kv_cnt = 0;
    scbp->poolstats.blk_cnt = 0;
    scbp->poolstats.byte_cnt = 0;

    pthread_mutex_init(&(scbp->poolmutex), NULL);
    pthread_cond_init(&(scbp->poolcond), NULL);

    scbp->rqueue = queue_new(ark->nasyncs);
    scbp->tqueue = queue_new(ark->ntasks);
    scbp->ioqueue = queue_new(ark->ntasks);

    pt->id = i;
    pt->ark = ark;
    rc = pthread_create(&(scbp->pooltid), NULL, pool_function, pt);
    if (rc != 0)
    {
      KV_TRC_FFDC(pAT, "pthread_create of server thread failed: %d", rc);
      goto ark_create_poolloop_err;
    }
  }

#if 0
  while (ark->nactive < ark->nthrds) {
    usleep(1);
    //printf("Create waiting %d/%d\n", ark->nactive, ark->nthrds);
  }
#endif

  ark->pcmd = PT_RUN;

  goto ark_create_return;

ark_create_poolloop_err:

  for (; i >= 0; i--)
  {
    scbp = &(ark->poolthreads[i]);

    if (scbp->pooltid != 0)
    {
      queue_lock(scbp->rqueue);
      queue_wakeup(scbp->rqueue);
      queue_unlock(scbp->rqueue);
      pthread_join(scbp->pooltid, NULL);

      pthread_mutex_destroy(&(scbp->poolmutex));
      pthread_cond_destroy(&(scbp->poolcond));

      if ( scbp->rqueue != NULL )
      {
        queue_free(scbp->rqueue);
      }

      if ( scbp->tqueue != NULL )
      {
        queue_free(scbp->tqueue);
      }
    
      if ( scbp->ioqueue != NULL )
      {
        queue_free(scbp->ioqueue);
      }
    }
  }

  if ( ark->pts != NULL )
  {
    am_free(ark->pts);
  }

ark_create_taskloop_err:
  for ( tnum = 0; tnum < ark->ntasks; tnum++ )
  {
    if (ark->tcbs[tnum].inb)
    {
      bt_delete(ark->tcbs[tnum].inb);
    }

    if (ark->tcbs[tnum].oub)
    {
      bt_delete(ark->tcbs[tnum].oub);
    }

    if (ark->tcbs[tnum].vb_orig)
    {
      am_free(ark->tcbs[tnum].vb_orig);
    }
  }

  for (rnum = 0; rnum < ark->nasyncs; rnum++)
  {
    pthread_cond_destroy(&(ark->rcbs[rnum].acond));
    pthread_mutex_destroy(&(ark->rcbs[rnum].alock));
  }

  if ( ark->poolthreads != NULL )
  {
    am_free(ark->poolthreads);
  }

ark_create_poolthreads_err:
  if (ark->iocbs)
  {
    am_free(ark->iocbs);
  }

ark_create_iocbs_err:
  if (ark->tcbs)
  {
    am_free(ark->tcbs);
  }

ark_create_tcbs_err:
  if (ark->rcbs)
  {
    am_free(ark->rcbs);
  }

ark_create_rcbs_err:
  if (ark->ttags)
  {
    tag_free(ark->ttags);
  }

ark_create_ttag_err:
  if (ark->rtags)
  {
    tag_free(ark->rtags);
  }

ark_create_rtag_err:
  pthread_mutex_destroy(&ark->mainmutex);

ark_create_pth_mutex_err:
  bl_delete(ark->bl);

ark_create_bl_err:
  hash_free(ark->ht);

ark_create_ht_err:
ark_create_persist_err:
  ea_delete(ark->ea);

ark_create_ea_err:
  am_free(ark);
  *arkret = NULL;

ark_create_ark_err:
  KV_TRC_CLOSE(pAT);

ark_create_return:
  return rc;
}
示例#25
0
int ark_check_persistence(_ARK *_arkp, uint64_t flags)
{
  int32_t  rc = -1;
  char    *p_data_orig = NULL;
  char    *p_data = NULL;
  ark_io_list_t *bl_array = NULL;
  p_cntr_t *pptr = NULL;
  P_ARK_t  *pcfg = NULL;
  hash_t   *htp = NULL;
  BL       *blp = NULL;
  uint64_t  rdblks = 0;

  if (flags & ARK_KV_PERSIST_LOAD) {KV_TRC(pAT, "PERSIST_LOAD");}

  // Ignore the persistence data and load from scratch
  if ( (!(flags & ARK_KV_PERSIST_LOAD)) || (flags & ARK_KV_VIRTUAL_LUN) )
  {
    return -1;
  }

  p_data_orig = am_malloc(_arkp->bsize);
  if (p_data_orig == NULL)
  {
    KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" bytes for the first "
                     "persistence block", _arkp->bsize);
    rc = ENOMEM;
  }
  else
  {
    p_data = ptr_align(p_data_orig);
    bl_array = bl_chain_no_bl(0, 1);
    rc = ea_async_io(_arkp->ea, ARK_EA_READ, (void *)p_data, 
                      bl_array, 1, 1);
    am_free(bl_array);
  }

  if (rc == 0)
  {
    // We've read the first block.  We check to see if
    // persistence data is present and if so, then
    // read the rest of the data from the flash.
    pptr = (p_cntr_t *)p_data;
    _arkp->persdata = p_data_orig;
    if ( memcmp(pptr->p_cntr_magic, ARK_P_MAGIC, 
                 sizeof(pptr->p_cntr_magic) != 0))
    {
      KV_TRC_FFDC(pAT, "No magic number found in persistence data: %d", EINVAL);
      // The magic number does not match so data is either
      // not present or is corrupted.
      rc = -1;
    }
    else
    {
      // Now we check version and the first persistence data
      // needs to be the ARK_PERSIST_CONFIG block
      if (pptr->p_cntr_version != ARK_P_VERSION_1 &&
          pptr->p_cntr_version != ARK_P_VERSION_2)
      {
        KV_TRC_FFDC(pAT, "Invalid / unsupported version: %"PRIu64"",
                    pptr->p_cntr_version);
        rc = EINVAL;
      }
      else
      {
        // Read in the rest of the persistence data
        pcfg   = (P_ARK_t *)(pptr->p_cntr_data + pptr->p_cntr_cfg_offset);
        rdblks = pcfg->pblocks;
        if (rdblks > 1)
        {
          p_data_orig = am_realloc(p_data_orig, (rdblks * _arkp->bsize));
          if (p_data_orig == NULL)
          {
            KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" bytes for "
                             "full persistence block",
                             (rdblks * _arkp->bsize));
            rc = ENOMEM;
          }
          else
          {
            p_data = ptr_align(p_data_orig);
            bl_array = bl_chain_no_bl(0, rdblks);
            if (bl_array == NULL)
            {
              KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" blocks for "
                               "full persistence data", rdblks);
              rc = ENOMEM;
            }
          }

          // We are still good to read the rest of the data
          // from the flash
          if (rc == 0)
          {
            KV_TRC(pAT, "PERSIST_RD rdblks:%ld", rdblks);
            rc = ea_async_io(_arkp->ea, ARK_EA_READ, (void *)p_data,
                           bl_array, rdblks, 1);
            am_free(bl_array);
            pptr = (p_cntr_t *)p_data;
            pcfg   = (P_ARK_t *)(pptr->p_cntr_data + pptr->p_cntr_cfg_offset);
            _arkp->persdata = p_data_orig;
          }
        }
      }
    }
  }

  // If rc == 0, that means we have persistence data
  if (rc == 0)
  {
      KV_TRC(pAT, "PERSIST_META size %ld bsize %ld hcount %ld bcount %ld "
                  "nthrds %d nasyncs %d basyncs %d blkbits %ld version:%ld",
                  pcfg->size, pcfg->bsize, pcfg->hcount, pcfg->bcount,
                  pcfg->nthrds, pcfg->nasyncs, pcfg->basyncs, pcfg->blkbits,
                  pptr->p_cntr_version);

    _arkp->persload            = 1;
    _arkp->size                = pcfg->size;
    _arkp->flags               = flags;
    _arkp->bsize               = pcfg->bsize;
    _arkp->bcount              = pcfg->bcount;
    _arkp->blkbits             = pcfg->blkbits;
    _arkp->grow                = pcfg->grow;
    _arkp->hcount              = pcfg->hcount;
    _arkp->vlimit              = pcfg->vlimit;
    _arkp->blkused             = pcfg->blkused;
    _arkp->pers_stats.kv_cnt   = pcfg->pstats.kv_cnt;
    _arkp->pers_stats.blk_cnt  = pcfg->pstats.blk_cnt;
    _arkp->pers_stats.byte_cnt = pcfg->pstats.byte_cnt;

    KV_TRC(pAT, "ARK_META size %ld bsize %ld hcount %ld bcount %ld "
                "nthrds %d nasyncs %ld basyncs %d blkbits %ld",
                _arkp->size, _arkp->bsize, _arkp->hcount, _arkp->bcount,
                _arkp->nthrds, _arkp->nasyncs, _arkp->basyncs, _arkp->blkbits);

    htp = (hash_t *)(pptr->p_cntr_data + pptr->p_cntr_ht_offset);
    _arkp->ht = hash_new(htp->n);
    if (_arkp->ht == NULL)
    {
        if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
        rc = errno;
        KV_TRC_FFDC(pAT, "ht_new failed: n:%ld rc:%d", htp->n, rc);
        goto error_exit;
    }
    memcpy(_arkp->ht, htp, pptr->p_cntr_ht_size);

    blp = (BL *)(pptr->p_cntr_data + pptr->p_cntr_bl_offset);
    _arkp->bl = bl_new(blp->n, blp->w);
    if (_arkp->bl == NULL)
    {
        if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
        rc = errno;
        KV_TRC_FFDC(pAT, "bl_new failed: n:%ld w:%ld rc:%d",
                    blp->n, blp->w, rc);
        goto error_exit;
    }
    _arkp->bl->count = blp->count;
    _arkp->bl->head  = blp->head;
    _arkp->bl->hold  = blp->hold;
    _arkp->bl->top   = blp->top;

    if (pptr->p_cntr_version == ARK_P_VERSION_1)
    {
        IV *piv = (IV *)(pptr->p_cntr_data + pptr->p_cntr_bliv_offset);

        KV_TRC(pAT, "PERSIST_VERSION_1 LOADED");
        _arkp->bl->top = _arkp->bl->n;

        // copy IV->data from piv->data
        memcpy(_arkp->bl->list->data,
               piv->data,
               pptr->p_cntr_bliv_size);
    }
    else if (pptr->p_cntr_version == ARK_P_VERSION_2)
    {
        KV_TRC(pAT, "PERSIST_VERSION_2 LOADED");
        // copy IV->data from bliv_offset
        memcpy(_arkp->bl->list->data,
               pptr->p_cntr_data + pptr->p_cntr_bliv_offset,
               pptr->p_cntr_bliv_size);
    }
    else
    {
        rc = EINVAL;
        KV_TRC_FFDC(pAT, "bad persistent version number: ver:%ld",
                    pptr->p_cntr_version);
        goto error_exit;
    }

    KV_TRC(pAT, "BL_META: n:%ld count:%ld head:%ld hold:%ld top:%ld",
            _arkp->bl->n, _arkp->bl->count, _arkp->bl->head, _arkp->bl->hold,
            _arkp->bl->top);
  }

error_exit:
  am_free(p_data_orig);
  return rc;
}
示例#26
0
int ark_persist(_ARK *_arkp)
{
  int32_t        rc          = 0;
  uint64_t       tot_bytes   = 0;
  uint64_t       wrblks      = 0;
  char          *p_data_orig = NULL;
  char          *p_data      = NULL;
  p_cntr_t      *pptr        = NULL;
  char          *dptr        = NULL;
  P_ARK_t       *pcfg        = NULL;
  ark_io_list_t *bl_array    = NULL;

  if ( (_arkp->ea->st_type == EA_STORE_TYPE_MEMORY) ||
      !(_arkp->flags & ARK_KV_PERSIST_STORE) )
  {
    return 0;
  }

  ark_persistence_calc(_arkp);

  // allocate write buffer
  tot_bytes   = _arkp->pers_max_blocks * _arkp->bsize;
  p_data_orig = am_malloc(tot_bytes);
  if (p_data_orig == NULL)
  {
    KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" bytes for "
                     "persistence data", tot_bytes);
    return ENOMEM;
  }
  memset(p_data_orig, 0, tot_bytes);
  p_data = ptr_align(p_data_orig);

  // Record cntr data
  pptr   = (p_cntr_t *)p_data;
  memcpy(pptr->p_cntr_magic, ARK_P_MAGIC, sizeof(pptr->p_cntr_magic));
  pptr->p_cntr_version = ARK_P_VERSION_2;
  pptr->p_cntr_size    = sizeof(p_cntr_t);

  // Record configuration info
  pcfg = (P_ARK_t*)pptr->p_cntr_data;
  pcfg->flags   = _arkp->flags;
  pcfg->size    = _arkp->ea->size;
  pcfg->bsize   = _arkp->bsize;
  pcfg->bcount  = _arkp->bcount;
  pcfg->blkbits = _arkp->blkbits;
  pcfg->grow    = _arkp->blkbits;
  pcfg->hcount  = _arkp->hcount;
  pcfg->vlimit  = _arkp->vlimit;
  pcfg->blkused = _arkp->blkused;
  pcfg->nasyncs = _arkp->nasyncs;
  pcfg->basyncs = _arkp->basyncs;
  pcfg->ntasks  = _arkp->ntasks;
  pcfg->nthrds  = _arkp->nthrds;
  ark_persist_stats(_arkp, &(pcfg->pstats));
  pptr->p_cntr_cfg_offset = 0;
  pptr->p_cntr_cfg_size   = sizeof(P_ARK_t);

  dptr = pptr->p_cntr_data;

  // Record hash info
  dptr                  += pptr->p_cntr_cfg_size;
  pptr->p_cntr_ht_offset = dptr - pptr->p_cntr_data;
  pptr->p_cntr_ht_size   = sizeof(hash_t) + (_arkp->ht->n * sizeof(uint64_t));
  memcpy(dptr, _arkp->ht, pptr->p_cntr_ht_size);

  // Record block list info
  dptr                  += pptr->p_cntr_ht_size;
  pptr->p_cntr_bl_offset = dptr - pptr->p_cntr_data;
  pptr->p_cntr_bl_size   = sizeof(BL);
  memcpy(dptr, _arkp->bl, pptr->p_cntr_bl_size);

  // Record IV list info
  dptr                    += pptr->p_cntr_bl_size;
  pptr->p_cntr_bliv_offset = dptr - pptr->p_cntr_data;

  // bliv_size = bytes in bl->list->data[cs_blocks + kvdata_blocks]
  // add 2 to top because of how IV->data chaining works
  pptr->p_cntr_bliv_size = divup((_arkp->bl->top+2) * _arkp->bl->w, 8);
  memcpy(dptr, _arkp->bl->list->data, pptr->p_cntr_bliv_size);

  // Calculate wrblks: number of persist metadata blocks to write
  tot_bytes = _arkp->pers_cs_bytes + pptr->p_cntr_bliv_size;
  wrblks    = pcfg->pblocks = divup(tot_bytes, _arkp->bsize);

  KV_TRC(pAT, "PERSIST_WR dev:%s top:%ld wrblks:%ld vs pers_max_blocks:%ld",
         _arkp->ea->st_device, _arkp->bl->top, pcfg->pblocks,
         _arkp->pers_max_blocks);

  bl_array = bl_chain_blocks(_arkp->bl, 0, wrblks);
  if ( NULL == bl_array )
  {
    KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" blocks for block list",
                wrblks);
    rc = ENOMEM;
  }
  else
  {
    rc = ea_async_io(_arkp->ea, ARK_EA_WRITE, (void *)p_data, 
                     bl_array, wrblks, _arkp->nthrds);
    am_free(bl_array);
  }

  KV_TRC(pAT, "PERSIST_DATA_STORED rc:%d", rc);

  am_free(p_data_orig);
  return rc;
}
示例#27
0
/**
 * Same as am_mysql_query_return_row_0
 * but given the mysql handle and the formatted query
 * Return NULL on error, the values of row[0][0] on success
 * The caller will need to free the result.
 */
char *
_am_mysql_query_return_row_0 (MYSQL *mysql, char *fmt_query){
  MYSQL_RES			*result = NULL;
  MYSQL_ROW     row;
  unsigned long *lengths;
  char *res = NULL;
  my_ulonglong  num_rows;


	/* Now for the query itself */
	if (mysql_query(mysql, fmt_query))
	{
		/* query failed */
		res = NULL;
		LOGERROR ("Failed to execute query: Error (%d): %s\n", mysql_errno(mysql), mysql_error(mysql));
		goto _query_return_row_0_free;
	}

	if ((result = mysql_store_result(mysql)) == NULL)
	{
		/*
		* Failed to get result
		* 2 cases:
		*		- no result expected (after an insert statement...
		*		- error getting result
		*/
		if (mysql_field_count (mysql) == 0){
			/* insert like statement, should not happen!; */
			res = NULL;
			goto _query_return_row_0_free;
		}else{
			res = NULL;
			LOGERROR ("Failed to store query results: Error (%d): %s\n", mysql_errno(mysql), mysql_error(mysql));
			goto _query_return_row_0_free;
		}
	}
  num_rows = mysql_num_rows(result);
	/* If num_rows > 1, we consider it is an error */
	if (num_rows > 1 ){
    res = NULL;
    LOGERROR ("Many results were found while only 1 was expected!\n");
    goto _query_return_row_0_free;
  }
  if (num_rows == 0){
    /* no result found */
    res = NULL;
    goto _query_return_row_0_free;
  }
  /* If we dont have any fields, we should fail too */
  if (mysql_num_fields(result) < 1 ){
    res = NULL;
    LOGERROR ("No field encountered in MySQL result!\n");
    goto _query_return_row_0_free;
  }

  row = mysql_fetch_row(result);
  if (row == NULL){
    /* An error occurred */
    res = NULL;
    LOGERROR ("Failed to return first row, Error (%d): %s\n", mysql_errno(mysql), mysql_error(mysql));
    goto _query_return_row_0_free;
  }
  lengths = mysql_fetch_lengths(result);
  if ( lengths[0] != 0 ){
    res = am_malloc (lengths[0] + 1);
    if (res == NULL){
      LOGERROR ("Could not allocate memory for result\n");
    }else{
      memcpy (res, row[0], lengths[0]);
      res[lengths[0]] = '\0';
    }
  }else{
    res = NULL;
  }
_query_return_row_0_free:
  if (result != NULL)
    mysql_free_result (result);
  return res;
}
示例#28
0
EA *ea_new(const char *path, uint64_t bsize, int basyncs,
           uint64_t *size, uint64_t *bcount, uint64_t vlun)
{
    int             rc    = 0;
    size_t          plen  = 0;
    uint8_t        *store = NULL;
    EA             *ea    = NULL;
    chunk_id_t      chkid = NULL_CHUNK_ID;
    chunk_ext_arg_t ext   = 0;

    if (!(fetch_and_or(&cflsh_blk_lib_init,1)))
    {
        // We need to call cblk_init once before
        // we use any other cblk_ interfaces
        rc = cblk_init(NULL,0);
        if (rc)
        {
            KV_TRC_FFDC(pAT, "cblk_init failed path %s bsize %"PRIu64" "
                             "size %"PRIu64" bcount %"PRIu64", errno = %d",
                             path, bsize, *size, *bcount, errno);
            goto error_exit;
        }
    }

    ea = am_malloc(sizeof(EA));
    if (NULL == ea)
    {
        KV_TRC_FFDC(pAT, "Out of memory path %s bsize %"PRIu64" size %"PRIu64" "
                         "bcount %"PRIu64", errno = %d",
                         path, bsize, *size, *bcount, errno);
        goto error_exit;
    }

    // We need to check the path parameter to see if
    // we are going to use memory or a file/capi
    // device (to be determined by the block layer)
    if ( (NULL == path) || (strlen(path) == 0) )
    {
        KV_TRC(pAT, "EA_STORE_TYPE_MEMORY");
        // Using memory for store
        ea->st_type = EA_STORE_TYPE_MEMORY;

        store = malloc(*size);
        if (NULL == store)
        {
            errno = ENOMEM;
            KV_TRC_FFDC(pAT, "Out of memory for store path %s bsize %"PRIu64" "
                             "size %"PRIu64" bcount %"PRIu64", errno = %d",
                             path, bsize, *size, *bcount, errno);
            goto error_exit;
        }

        *bcount = ((*size) / bsize);
        ea->st_memory = store;
    }
    else
    {
        KV_TRC(pAT, "EA_STORE_TYPE_FILE(%s)", path);

        // Using a file.  We don't care if it's an actual
        // file or a CAPI device, we let block layer
        // decide and we just use the chunk ID that is
        // passed back from the cblk_open call.
        ea->st_type = EA_STORE_TYPE_FILE;

        // Check to see if we need to create the store on a
        // physical or virtual LUN.  Previously, in GA1,
        // we keyed off the size and if it was 0, then we
        // asked for the LUN to be physical.  Now, the user
        // can specify with a flag.
        if ( vlun == 0 )
        {
            KV_TRC(pAT, "cblk_open PHYSICAL LUN: %s", path);
            chkid = cblk_open(path, basyncs, O_RDWR, ext,
                              CBLK_OPN_NO_INTRP_THREADS);

            if (NULL_CHUNK_ID == chkid)
            {
                printf("cblk_open physical lun failed\n");
                KV_TRC_FFDC(pAT, "cblk_open phys lun failed path:%s bsize:%ld "
                                 "size:%ld bcount:%ld, errno:%d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            rc = cblk_get_size(chkid, (size_t *)bcount, 0);
            if ( (rc != 0) || (*bcount == 0) )
            {
                // An error was encountered, close the chunk
                cblk_close(chkid, 0);
                chkid = NULL_CHUNK_ID;
                KV_TRC_FFDC(pAT, "cblk_get_size failed path %s bsize %"PRIu64" "
                                 "size %"PRIu64" bcount %"PRIu64", errno = %d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            // Set the size to be returned
            *size = *bcount * bsize;
        }
        else
        {
            KV_TRC(pAT, "cblk_open VIRTUAL LUN: %s", path);
            chkid = cblk_open(path, basyncs, O_RDWR, ext,
                              CBLK_OPN_VIRT_LUN|CBLK_OPN_NO_INTRP_THREADS);

            if (NULL_CHUNK_ID == chkid)
            {
                printf("cblk_open virtual lun failed\n");
                KV_TRC_FFDC(pAT, "cblk_open virt lun failed path:%s bsize:%ld "
                                 "size:%ld bcount:%ld, errno:%d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            // A specific size was passed in so we try to set the
            // size of the chunk.
            *bcount = *size / bsize;
            rc = cblk_set_size(chkid, (size_t)*bcount, 0);
            if ( rc != 0 )
            {
                printf("cblk_set_size failed for %ld\n", *bcount);
                // An error was encountered, close the chunk
                cblk_close(chkid, 0);
                chkid = NULL_CHUNK_ID;
                KV_TRC_FFDC(pAT, "cblk_set_size failed path %s bsize %"PRIu64" "
                                 "size %"PRIu64" bcount %"PRIu64", errno = %d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }
        }

        // Save off the chunk ID and the device name
        ea->st_flash  = chkid;
        plen          = strlen(path) + 1;
        ea->st_device = (char *)am_malloc(plen);
        if (!ea->st_device)
        {
            cblk_close(chkid, 0);
            KV_TRC_FFDC(pAT, "MALLOC st_device failed (%s) plen=%ld errno:%d",
                        path, plen, errno);
            goto error_exit;
        }

        memset(ea->st_device, 0, plen);
        strncpy(ea->st_device, path, plen);
    }

    // Fill in the EA struct
    pthread_rwlock_init(&(ea->ea_rwlock), NULL);
    ea->bsize  = bsize;
    ea->bcount = *bcount;
    ea->size   = *size;

    KV_TRC(pAT, "path %s bsize %"PRIu64" size %"PRIu64" bcount %"PRIu64"",
           path, bsize, *size, *bcount);
    goto done;

error_exit:
    am_free(ea);
    ea = NULL;
    if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOSPC;}

done:
    return ea;
}