/**
 * hg_gstate_set_dash:
 * @gstate:
 * @qpattern:
 * @offset:
 *
 * FIXME
 *
 * Returns:
 */
hg_bool_t
hg_gstate_set_dash(hg_gstate_t *gstate,
		   hg_quark_t   qpattern,
		   hg_real_t    offset)
{
	hg_array_t *a;
	hg_mem_t *mem;
	hg_uint_t id;
	hg_usize_t i;
	hg_bool_t is_zero = TRUE;

	hg_return_val_if_fail (gstate != NULL, FALSE, HG_e_typecheck);
	hg_return_val_if_fail (HG_IS_QARRAY (qpattern), FALSE, HG_e_typecheck);

	/* initialize hg_errno to estimate properly */
	hg_errno = 0;

	id = hg_quark_get_mem_id(qpattern);

	hg_return_val_if_fail ((mem = hg_mem_spool_get(id)) != NULL, FALSE, HG_e_VMerror);
	hg_return_val_if_lock_fail (a, mem, qpattern, FALSE);

	if (hg_array_length(a) > 11) {
		hg_debug(HG_MSGCAT_GSTATE, "Array size for dash pattern is too big");
		hg_errno = HG_ERROR_ (HG_STATUS_FAILED, HG_e_limitcheck);
		goto finalize;
	}
	if (hg_array_length(a) > 0) {
		for (i = 0; i < hg_array_length(a); i++) {
			hg_quark_t q = hg_array_get(a, i);

			if (!HG_ERROR_IS_SUCCESS0 ())
				return FALSE;
			if (HG_IS_QINT (q)) {
				if (HG_INT (q) != 0)
					is_zero = FALSE;
			} else if (HG_IS_QREAL (q)) {
				if (!HG_REAL_IS_ZERO (q))
					is_zero = FALSE;
			} else {
				hg_debug(HG_MSGCAT_GSTATE, "Dash pattern contains non-numeric.");
				hg_errno = HG_ERROR_ (HG_STATUS_FAILED, HG_e_typecheck);
				goto finalize;
			}
		}
		if (is_zero) {
			hg_debug(HG_MSGCAT_GSTATE, "No patterns in Array");
			hg_errno = HG_ERROR_ (HG_STATUS_FAILED, HG_e_rangecheck);
			goto finalize;
		}
	}

	gstate->qdashpattern = qpattern;
	gstate->dash_offset = offset;
  finalize:
	hg_mem_unlock_object(mem, qpattern);

	return HG_ERROR_IS_SUCCESS0 ();
}
hg_graph_t * hg_hyperbolic_standard(const int n, const double k_bar, 
				    const double exp_gamma,
				    const double temperature,			 			       
				    const double zeta, const int seed, 
				    bool verbose) {
  if(verbose) {
    cout << "-> Hyperbolic Standard Graph" << endl << endl;
  }
  hg_graph_t * graph = new hg_graph_t(n);
  if(graph == NULL) {
    hg_log_warn("Unable to allocate memory for graph object");
    return NULL;
  }
  // init graph
  hg_init_graph(graph, n, k_bar, exp_gamma, temperature,
		zeta, seed, HYPERBOLIC_STANDARD);
  // computing internal parameters
  hg_debug("\tInternal parameters computation");
  hg_algorithm_parameters_t p;
  // alpha calculation. different for cold and hot regimes
  if(temperature <= 1) {
    p.alpha = 0.5 * zeta * (exp_gamma-1.0);
  }
  else {
    p.alpha = 0.5 * zeta/temperature * (exp_gamma-1.0);
  }
  p.eta = -1; // not relevant for current model
  p.c = -1;  // not relevant for current model
  p.radius = hg_get_R_from_numerical_integration(graph, p);
  hg_debug("\tInternal parameters:");
  hg_debug("\t\tAlpha: %f", p.alpha);
  hg_debug("\t\tRadius: %f", p.radius);
  r_precomputedsinhcosh r_psc; 
  hg_assign_coordinates(graph, p, &r_psc);
  hg_coordinate_t c1, c2;
  int id, other_id;
  hg_debug("\tCreating links");
  for(id = 0; id < (*graph)[boost::graph_bundle].expected_n; id++) {
    c1 = hg_get_coordinate(graph, id);
    for(other_id = id+1; other_id < (*graph)[boost::graph_bundle].expected_n; other_id++) {
      c2 = hg_get_coordinate(graph, other_id);
      if(HG_Random::get_random_01_value() < hg_connection_probability_hyperbolic_standard(graph, p, c1, c2, &r_psc)) {
	add_edge(id, other_id, *graph);
	//hg_debug("\t\tNew link: %d - %d ", id, other_id);
      }
    }
  }
  return graph;
}
static void hg_assign_coordinates(hg_graph_t * graph, const hg_algorithm_parameters_t & in_par,
				  r_precomputedsinhcosh * r_psc = NULL) {
  hg_debug("\tAssigning coordinates");
  int id; // node identifier [0,n-1]
  switch((*graph)[boost::graph_bundle].type){
  case HYPERBOLIC_RGG: 
  case HYPERBOLIC_STANDARD:
  case SOFT_CONFIGURATION_MODEL:
    for(id = 0; id < (*graph)[boost::graph_bundle].expected_n; id++) {
      double zeta = (*graph)[boost::graph_bundle].zeta_eta;
      double r = hg_quasi_uniform_radial_coordinate(in_par.radius, in_par.alpha);
      (*graph)[id].r = r;
      if(r_psc != NULL) {
	(*r_psc).insert(make_pair(r, make_pair(sinh(zeta * r), cosh(zeta * r))));
      }
      (*graph)[id].theta = hg_uniform_angular_coordinate();
    }
    break;
  case ANGULAR_RGG:
  case SOFT_RGG:
  case ERDOS_RENYI:
    for(id = 0; id < (*graph)[boost::graph_bundle].expected_n; id++) {
      (*graph)[id].r = in_par.radius; // HG_INF_RADIUS
      (*graph)[id].theta = hg_uniform_angular_coordinate();
    }
    break;
  default:
    hg_log_err("Case not implemented.");
  }
}
hg_graph_t * hg_soft_configuration_model(const int n, const double k_bar, 
					 const double exp_gamma,
					 const double eta, const int seed, 
					 bool verbose) {
  if(verbose) {
    cout << "-> Soft Configuration Model Graph" << endl << endl;
  }
  hg_graph_t * graph = new hg_graph_t(n);
  if(graph == NULL) {
    hg_log_warn("Unable to allocate memory for graph object");
    return NULL;
  }
  // init graph
  hg_init_graph(graph, n, k_bar, exp_gamma, HG_INF_TEMPERATURE /* t = inf */,
		eta, seed, SOFT_CONFIGURATION_MODEL);
  // computing internal parameters
  hg_debug("\tInternal parameters computation");
  // zeta goes to infinity
  //(*graph)[boost::graph_bundle].zeta_eta = numeric_limits<double>::max( );
  hg_algorithm_parameters_t p;
  p.eta = (*graph)[boost::graph_bundle].zeta_eta;
  p.alpha = 0.5 * p.eta * (exp_gamma-1.0);
  p.c = -1;  // not relevant for current model
  p.radius = hg_get_R_from_numerical_integration(graph, p);
  hg_debug("\t\talpha: %f", p.alpha);
  hg_debug("\t\teta: %f", p.eta);
  hg_debug("\t\tradius: %f", p.radius);
  hg_assign_coordinates(graph, p);
  hg_coordinate_t c1, c2;
  int id, other_id;
  hg_debug("\tCreating links");
  for(id = 0; id < (*graph)[boost::graph_bundle].expected_n; id++) {
    c1 = hg_get_coordinate(graph, id);
    for(other_id = id+1; other_id < (*graph)[boost::graph_bundle].expected_n; other_id++) {
      c2 = hg_get_coordinate(graph, other_id);
      if(HG_Random::get_random_01_value() < hg_connection_probability_scm(graph, p, c1, c2)) {
	add_edge(id, other_id, *graph);
	//hg_debug("\t\tNew link: %d - %d ", id, other_id);
      }
    }
  }
  return graph;
}
static hg_bool_t
_hg_object_dict_gc_mark(hg_object_t *object)
{
	hg_dict_t *dict;

	hg_return_val_if_fail (object->type == HG_TYPE_DICT, FALSE, HG_e_VMerror);

	dict = (hg_dict_t *)object;
	hg_debug(HG_MSGCAT_GC, "dict: marking a root dict node.");

	return hg_mem_gc_mark(dict->o.mem, dict->qroot);
}
hg_graph_t * hg_soft_rgg(const int n, const double k_bar, 
			 const double temperature,			 
			 const double zeta, const int seed, 
			 bool verbose) {
  if(verbose) {
    cout << "-> Soft Random Geometric Graph" << endl << endl;
  }
  hg_graph_t * graph = new hg_graph_t(n);
  if(graph == NULL) {
    hg_log_warn("Unable to allocate memory for graph object");
    return NULL;
  }
  // init graph
  hg_init_graph(graph, n, k_bar, HG_INF_GAMMA /* exp_gamma = inf */, temperature /* t = 0 */,
		zeta, seed, SOFT_RGG);
  // computing internal parameters
  hg_debug("\tInternal parameters computation");
  hg_algorithm_parameters_t p;
  p.radius = HG_INF_RADIUS; 
  p.alpha = -1; // not relevant for current model
  p.eta = -1; // not relevant for current model
  p.c = hg_get_lambda_from_Gauss_hypergeometric_function(graph,p); 
  hg_assign_coordinates(graph, p);
  hg_coordinate_t c1, c2;
  int id, other_id;
  hg_debug("\tCreating links");
  for(id = 0; id < (*graph)[boost::graph_bundle].expected_n; id++) {
    c1 = hg_get_coordinate(graph, id);
    for(other_id = id+1; other_id < (*graph)[boost::graph_bundle].expected_n; other_id++) {
      c2 = hg_get_coordinate(graph, other_id);
      if(HG_Random::get_random_01_value() < hg_connection_probability_soft_rgg(graph, p, c1, c2)) {
	add_edge(id, other_id, *graph);
	hg_debug("\t\tNew link: %d - %d ", id, other_id);
      }
    }
  }
  return graph;
}
HG_INLINE_FUNC hg_bool_t
_hg_dict_node_insert(hg_mem_t   *mem,
		     hg_quark_t  qnode,
		     hg_quark_t *qkey,
		     hg_quark_t *qval,
		     hg_quark_t *qright_node)
{
	hg_usize_t i;
	hg_bool_t retval = FALSE;
	hg_dict_node_t *qnode_node = NULL;
	hg_quark_t *qnode_keys = NULL, *qnode_vals = NULL, *qnode_nodes = NULL;

	if (qnode == Qnil) {
		*qright_node = Qnil;
		return FALSE;
	}
	HG_DICT_NODE_LOCK (mem, qnode, qnode, "");

	if (qnode_keys[qnode_node->n_data - 1] >= *qkey) {
		for (i = 0; i < qnode_node->n_data && qnode_keys[i] < *qkey; i++);
		if (i < qnode_node->n_data && qnode_keys[i] == *qkey) {
			hg_debug(HG_MSGCAT_DICT, "Inserting val %lx with key %lx at index %lx on node %p\n", *qval, *qkey, i, qnode_nodes);
			qnode_keys[i] = *qkey;
			qnode_vals[i] = *qval;

			retval = TRUE;
			goto finalize;
		}
	} else {
		i = qnode_node->n_data;
	}
	retval = _hg_dict_node_insert(mem, qnode_nodes[i], qkey, qval, qright_node);
	if (!HG_ERROR_IS_SUCCESS0 ()) {
		retval = FALSE;
		goto finalize;
	}
	if (!retval) {
		if (qnode_node->n_data < (__hg_dict_node_size * 2)) {
			_hg_dict_node_insert_data(qnode_node, qnode_keys, qnode_vals, qnode_nodes, *qkey, *qval, i, qright_node);
			retval = TRUE;
		} else {
			_hg_dict_node_balance(qnode_node, qnode_keys, qnode_vals, qnode_nodes, qkey, qval, i, qright_node);
			retval = FALSE;
		}
	}
  finalize:
	HG_DICT_NODE_UNLOCK (mem, qnode, qnode);

	return retval;
}
hg_graph_t * hg_erdos_renyi(const int n, const double k_bar, 			     
			    const double zeta, const int seed, 
			    bool verbose) {
  if(verbose) {
    cout << "-> Erdos-Renyi Graph" << endl << endl;
  }
  hg_graph_t * graph = new hg_graph_t(n);
  if(graph == NULL) {
    hg_log_warn("Unable to allocate memory for graph object");
    return NULL;
  }
  // init graph
  hg_init_graph(graph, n, k_bar, HG_INF_GAMMA /* exp_gamma = inf */, HG_INF_TEMPERATURE /* t = inf */,
		zeta, seed, ERDOS_RENYI);
  // computing internal parameters
  hg_debug("\tInternal parameters computation");
  hg_algorithm_parameters_t p;
  p.radius = HG_INF_RADIUS; 
  p.alpha = -1; // not relevant for current model
  p.eta = -1; // not relevant for current model
  hg_debug("\t\tradius: %d (INF)", HG_INF_RADIUS);
  hg_assign_coordinates(graph, p);
  hg_coordinate_t c1, c2;
  int id, other_id;
  hg_debug("\tCreating links");
  for(id = 0; id < (*graph)[boost::graph_bundle].expected_n; id++) {
    c1 = hg_get_coordinate(graph, id);
    for(other_id = id+1; other_id < (*graph)[boost::graph_bundle].expected_n; other_id++) {
      c2 = hg_get_coordinate(graph, other_id);      
      if(HG_Random::get_random_01_value() < hg_connection_probability_er(graph, c1, c2)) {
	add_edge(id, other_id, *graph);
	hg_debug("\t\tNew link: %d - %d ", id, other_id);
      }
    }
  }
  return graph;
}
static void hg_init_graph(hg_graph_t * graph, const int & n, const double & k_bar, 
			  const double & exp_gamma, const double & t, 
			  const double & zeta_eta, const int & seed, 
			  const hg_graph_type & gt) {
  hg_debug("\tGraph initialization");
  /* initialize the graph structure with the 
   * parameters provided in input by the user */
  (*graph)[boost::graph_bundle].type = gt;
  (*graph)[boost::graph_bundle].expected_n = n;
  (*graph)[boost::graph_bundle].temperature = t;
  (*graph)[boost::graph_bundle].expected_gamma = exp_gamma;
  (*graph)[boost::graph_bundle].expected_degree = k_bar;
  (*graph)[boost::graph_bundle].zeta_eta = zeta_eta;
  (*graph)[boost::graph_bundle].seed = seed;  
  // Init random generator
  HG_Random::init(seed);  
}
HG_INLINE_FUNC void
_hg_dict_node_insert_data(hg_dict_node_t *node,
			  hg_quark_t     *qkeys,
			  hg_quark_t     *qvals,
			  hg_quark_t     *qnodes,
			  hg_quark_t      qkey,
			  hg_quark_t      qval,
			  hg_usize_t      pos,
			  hg_quark_t     *qright_node)
{
	hg_usize_t i;

	for (i = node->n_data; i > pos; i--) {
		qkeys[i] = qkeys[i - 1];
		qvals[i] = qvals[i - 1];
		qnodes[i + 1] = qnodes[i];
	}
	hg_debug(HG_MSGCAT_DICT, "Inserting val %lx with key %lx at index %lx on node %p\n", qval, qkey, pos, qnodes);
	qkeys[pos] = qkey;
	qvals[pos] = qval;
	qnodes[pos + 1] = *qright_node;
	node->n_data++;
}
static hg_quark_t
_hg_object_gstate_copy(hg_object_t             *object,
		       hg_quark_iterate_func_t  func,
		       hg_pointer_t             user_data,
		       hg_pointer_t            *ret)
{
	hg_gstate_t *gstate = (hg_gstate_t *)object, *g = NULL;
	hg_quark_t retval;

	hg_return_val_if_fail (object->type == HG_TYPE_GSTATE, Qnil, HG_e_typecheck);

	if (object->on_copying != Qnil)
		return object->on_copying;

	object->on_copying = retval = hg_gstate_new(gstate->o.mem, (hg_pointer_t *)&g);
	if (retval != Qnil) {
		memcpy(&g->ctm, &gstate->ctm, sizeof (hg_gstate_t) - sizeof (hg_object_t) - (sizeof (hg_quark_t) * 3));
		if (gstate->qpath == Qnil) {
			g->qpath = Qnil;
		} else {
			g->qpath = func(gstate->qpath, user_data, NULL);
			if (g->qpath == Qnil) {
				hg_debug(HG_MSGCAT_GSTATE, "Unable to copy the path object");
				goto bail;
			}
			hg_mem_unref(gstate->o.mem,
				     g->qpath);
		}
		if (gstate->qclippath == Qnil) {
			g->qclippath = Qnil;
		} else {
			g->qclippath = func(gstate->qclippath, user_data, NULL);
			if (g->qclippath == Qnil) {
				hg_debug(HG_MSGCAT_GSTATE, "Unable to copy the clippath object");
				goto bail;
			}
			hg_mem_unref(gstate->o.mem,
				     g->qclippath);
		}
		if (gstate->qdashpattern == Qnil) {
			g->qdashpattern = Qnil;
		} else {
			g->qdashpattern = func(gstate->qdashpattern, user_data, NULL);
			if (g->qdashpattern == Qnil) {
				hg_debug(HG_MSGCAT_GSTATE, "Unable to copy the dashpattern object");
				goto bail;
			}
			hg_mem_unref(gstate->o.mem,
				     g->qdashpattern);
		}

		if (ret)
			*ret = g;
		else
			hg_mem_unlock_object(g->o.mem, retval);
	}
	goto finalize;
  bail:
	if (g) {
		hg_object_free(g->o.mem, retval);

		retval = Qnil;
	}
  finalize:
	object->on_copying = Qnil;

	return retval;
}
/**
 * hg_dict_add:
 * @dict:
 * @qkey:
 * @qval:
 * @force:
 *
 * FIXME
 *
 * Returns:
 */
hg_bool_t
hg_dict_add(hg_dict_t  *dict,
	    hg_quark_t  qkey,
	    hg_quark_t  qval,
	    hg_bool_t   force)
{
	hg_bool_t inserted;
	hg_dict_node_t *qnode_node;
	hg_quark_t new_node = Qnil, qnode, *qnode_keys = NULL, *qnode_vals = NULL, *qnode_nodes = NULL;
	hg_quark_t qmasked;
	hg_mem_t *m;

	hg_return_val_if_fail (dict != NULL, FALSE, HG_e_VMerror);
	hg_return_val_if_fail (dict->o.type == HG_TYPE_DICT, FALSE, HG_e_typecheck);
	hg_return_val_if_fail (!HG_IS_QSTRING (qkey), FALSE, HG_e_typecheck);

	/* initialize hg_errno to estimate properly */
	hg_errno = 0;

	if (!force &&
	    hg_mem_spool_get_type(dict->o.mem) == HG_MEM_TYPE_GLOBAL) {
		if (!(hg_quark_is_simple_object(qkey) ||
		      hg_quark_get_type(qkey) == HG_TYPE_OPER) &&
		    hg_mem_spool_get_type(hg_mem_spool_get(hg_quark_get_mem_id(qkey))) == HG_MEM_TYPE_LOCAL) {
			hg_debug(HG_MSGCAT_DICT, "Unable to store the object allocated in the local memory into the global memory");

			hg_error_return (HG_STATUS_FAILED, HG_e_invalidaccess);
		}
		if (!(hg_quark_is_simple_object(qval) ||
		      hg_quark_get_type(qval) == HG_TYPE_OPER) &&
		    hg_mem_spool_get_type(hg_mem_spool_get(hg_quark_get_mem_id(qval))) == HG_MEM_TYPE_LOCAL) {
			hg_debug(HG_MSGCAT_DICT, "Unable to store the object allocated in the local memory into the global memory");

			hg_error_return (HG_STATUS_FAILED, HG_e_invalidaccess);
		}
	}
	if (dict->raise_dictfull &&
	    hg_dict_length(dict) == hg_dict_maxlength(dict) &&
	    hg_dict_lookup(dict, qkey) == Qnil) {
		hg_debug(HG_MSGCAT_DICT, "no more spaces in the dict");

		hg_error_return (HG_STATUS_FAILED, HG_e_dictfull);
	}

	qmasked = hg_quark_get_hash(qkey);
	inserted = _hg_dict_node_insert(dict->o.mem, dict->qroot,
					&qmasked, &qval, &new_node);
	if (!HG_ERROR_IS_SUCCESS0 ())
		return FALSE;
	if (!inserted) {
		qnode = _hg_dict_node_new(dict->o.mem,
					  (hg_pointer_t *)&qnode_node,
					  (hg_pointer_t *)&qnode_keys,
					  (hg_pointer_t *)&qnode_vals,
					  (hg_pointer_t *)&qnode_nodes);
		if (qnode == Qnil) {
			return FALSE;
		}
		qnode_node->n_data = 1;
		qnode_keys[0] = qmasked;
		qnode_vals[0] = qval;
		qnode_nodes[0] = dict->qroot;
		qnode_nodes[1] = new_node;
		dict->qroot = qnode;

		HG_DICT_NODE_UNLOCK_NO_LABEL (dict->o.mem, qnode, qnode);
		hg_mem_unref(dict->o.mem, qnode);
	}
	if (!hg_quark_is_simple_object(qkey) &&
	    hg_quark_get_type(qkey) != HG_TYPE_OPER) {
		m = hg_mem_spool_get(hg_quark_get_mem_id(qkey));
		hg_mem_unref(m, qkey);
	}
	if (!hg_quark_is_simple_object(qval) &&
	    hg_quark_get_type(qval) != HG_TYPE_OPER) {
		m = hg_mem_spool_get(hg_quark_get_mem_id(qval));
		hg_mem_unref(m, qval);
	}
	dict->length++;

	return TRUE;
}
static hg_bool_t
_hg_object_dict_node_gc_mark(hg_object_t *object)
{
	hg_dict_node_t *dnode = (hg_dict_node_t *)object;
	hg_usize_t i;
	hg_quark_t *qnode_keys = NULL, *qnode_vals = NULL, *qnode_nodes = NULL;

	hg_return_val_if_fail (object->type == HG_TYPE_DICT_NODE, FALSE, HG_e_typecheck);

	hg_debug(HG_MSGCAT_GC, "dictnode: marking key container");
	if (!hg_mem_gc_mark(dnode->o.mem, dnode->qkey))
		return FALSE;
	hg_debug(HG_MSGCAT_GC, "dictnode: marking value container");
	if (!hg_mem_gc_mark(dnode->o.mem, dnode->qval))
		return FALSE;
	hg_debug(HG_MSGCAT_GC, "dictnode: marking node container");
	if (!hg_mem_gc_mark(dnode->o.mem, dnode->qnodes))
		return FALSE;

	qnode_keys = hg_mem_lock_object(dnode->o.mem, dnode->qkey);
	qnode_vals = hg_mem_lock_object(dnode->o.mem, dnode->qval);
	qnode_nodes = hg_mem_lock_object(dnode->o.mem, dnode->qnodes);
	if (qnode_keys == NULL ||
	    qnode_vals == NULL ||
	    qnode_nodes == NULL) {
		hg_critical("%s: Invalid quark to obtain the actual object in dnode",
			    __PRETTY_FUNCTION__);
		hg_errno = HG_ERROR_ (HG_STATUS_FAILED, HG_e_VMerror);
		goto qfinalize;
	}

	for (i = 0; i < dnode->n_data; i++) {
		hg_mem_t *m;

		hg_debug(HG_MSGCAT_GC, "dictnode: marking node[%ld]", i);
		if (!hg_mem_gc_mark(dnode->o.mem, qnode_nodes[i]))
			goto qfinalize;
		hg_debug(HG_MSGCAT_GC, "dictnode: marking key[%ld]", i);
		if (!hg_quark_is_simple_object(qnode_keys[i]) &&
		    hg_quark_get_type(qnode_keys[i]) != HG_TYPE_OPER) {
			m = hg_mem_spool_get(hg_quark_get_mem_id(qnode_keys[i]));
			if (!hg_mem_gc_mark(m, qnode_keys[i]))
				goto qfinalize;
		}
		hg_debug(HG_MSGCAT_GC, "dictnode: marking value[%ld]", i);
		if (!hg_quark_is_simple_object(qnode_vals[i]) &&
		    hg_quark_get_type(qnode_vals[i]) != HG_TYPE_OPER) {
			m = hg_mem_spool_get(hg_quark_get_mem_id(qnode_vals[i]));
			if (!hg_mem_gc_mark(m, qnode_vals[i]))
				goto qfinalize;
		}
	}
	hg_debug(HG_MSGCAT_GC, "dictnode: marking node[%ld]", dnode->n_data);
	if (!hg_mem_gc_mark(dnode->o.mem, qnode_nodes[dnode->n_data]))
		goto qfinalize;
  qfinalize:
	if (qnode_keys)
		hg_mem_unlock_object(dnode->o.mem, dnode->qkey);
	if (qnode_vals)
		hg_mem_unlock_object(dnode->o.mem, dnode->qval);
	if (qnode_nodes)
		hg_mem_unlock_object(dnode->o.mem, dnode->qnodes);

	return HG_ERROR_IS_SUCCESS0 ();
}