// Looked up the message in the store. Time to send the response value back to
// the requester. The CF_BYTEARRAY is handed off in this case. If you want to
// keep a reference, then keep the reference yourself.
int
as_proxy_send_response(cf_node dst, msg *m, uint32_t result_code, uint32_t generation,
		uint32_t void_time, as_msg_op **ops, as_bin **bins, uint16_t bin_count,
		as_namespace *ns, uint64_t trid, const char *setname)
{
	uint32_t tid;
	msg_get_uint32(m, PROXY_FIELD_TID, &tid);

#ifdef DEBUG
	cf_debug(AS_PROXY, "proxy send response: message %p bytearray %p tid %d", m, result_code, tid);
#endif

	msg_reset(m);

	msg_set_uint32(m, PROXY_FIELD_OP, PROXY_OP_RESPONSE);
	msg_set_uint32(m, PROXY_FIELD_TID, tid);

	size_t msg_sz = 0;
	cl_msg * msgp = as_msg_make_response_msg(result_code, generation, void_time, ops,
			bins, bin_count, ns, 0, &msg_sz, trid, setname);

	msg_set_buf(m, PROXY_FIELD_AS_PROTO, (byte *) msgp, msg_sz, MSG_SET_HANDOFF_MALLOC);

	int rv = as_fabric_send(dst, m, AS_FABRIC_PRIORITY_MEDIUM);
	if (rv != 0) {
		cf_debug(AS_PROXY, "sending proxy response: fabric send err %d, catch you on the retry", rv);
		as_fabric_msg_put(m);
	}

	return 0;
} // end as_proxy_send_response()
int
as_proxy_send_ops_response(cf_node dst, msg *m, cf_dyn_buf *db)
{
	uint32_t tid;
	msg_get_uint32(m, PROXY_FIELD_TID, &tid);

#ifdef DEBUG
	cf_debug(AS_PROXY, "proxy send response: message %p bytearray %p tid %d", m, result_code, tid);
#endif

	msg_reset(m);

	msg_set_uint32(m, PROXY_FIELD_OP, PROXY_OP_RESPONSE);
	msg_set_uint32(m, PROXY_FIELD_TID, tid);

	uint8_t *msgp = db->buf;
	size_t msg_sz = db->used_sz;

	if (db->is_stack) {
		msg_set_buf(m, PROXY_FIELD_AS_PROTO, msgp, msg_sz, MSG_SET_COPY);
	}
	else {
		msg_set_buf(m, PROXY_FIELD_AS_PROTO, msgp, msg_sz, MSG_SET_HANDOFF_MALLOC);
		db->buf = NULL; // the fabric owns the buffer now
	}

	int rv = as_fabric_send(dst, m, AS_FABRIC_PRIORITY_MEDIUM);
	if (rv != 0) {
		cf_debug(AS_PROXY, "sending proxy response: fabric send err %d, catch you on the retry", rv);
		as_fabric_msg_put(m);
	}

	return 0;
} // end as_proxy_send_ops_response()
Beispiel #3
0
/*
 * Check and validate parameter before performing operation
 *
 * return:
 *      2 : UDF_ERR_INTERNAL_PARAM
 *      3 : UDF_ERR_RECORD_IS_NOT_VALID
 *      4 : UDF_ERR_PARAMETER
 *      0 : Success
 *
 */
int
udf_record_param_check(const as_rec *rec, const char *bname, char *fname, int lineno)
{
	if (!rec || !bname) {
		cf_warning(AS_UDF, "Invalid Paramters: record=%p bname=%p", rec, bname);
		return UDF_ERR_INTERNAL_PARAMETER;
	} 

	udf_record * urecord = (udf_record *) as_rec_source(rec);
	if (!urecord) {
		return UDF_ERR_INTERNAL_PARAMETER;;
	}

	if (!(urecord->flag & UDF_RECORD_FLAG_ISVALID)) {
		if (!(urecord->flag & UDF_RECORD_FLAG_IS_SUBRECORD)) {
			cf_debug(AS_UDF, "(%s:%d): Trying to Open Invalid Record ", fname, lineno);
		} else {
			cf_debug(AS_UDF, "(%s:%d): Trying to Open Invalid SubRecord ", fname, lineno);
		}
		return UDF_ERR_RECORD_NOT_VALID;
	}

	as_namespace  * ns = urecord->tr->rsv.ns;
	if (strlen(bname) >= AS_ID_BIN_SZ || !as_bin_name_within_quota(ns, bname)) {
		cf_debug(AS_UDF, "Invalid Parameter: bin name %s too big", bname);
		return UDF_ERR_PARAMETER;
	}
	return 0;
}
Beispiel #4
0
void
udf_record_cache_free(udf_record * urecord)
{
	cf_debug(AS_UDF, "[ENTER] NumUpdates(%d) ", urecord->nupdates );

	for (uint32_t i = 0; i < urecord->nupdates; i ++ ) {
		udf_record_bin * bin = &urecord->updates[i];
		if ( bin->name[0] != '\0' && bin->value != NULL ) {
			bin->name[0] = '\0';
			as_val_destroy(bin->value);
			bin->value = NULL;
		}
		if ( bin->name[0] != '\0' && bin->oldvalue != NULL ) {
			bin->name[0] = '\0';
			as_val_destroy(bin->oldvalue);
			bin->oldvalue = NULL;
		}
	}

	for (uint32_t i = 0; i < UDF_RECORD_BIN_ULIMIT; i++) {
		if (urecord->updates[i].particle_buf) {
			cf_free(urecord->updates[i].particle_buf);
			urecord->updates[i].particle_buf = NULL;
		}
	}
	urecord->nupdates = 0;
	urecord->flag &= ~UDF_RECORD_FLAG_TOO_MANY_BINS;
}
/**
 * Add a FULL NODE Entry, which has port, group and node id inside
 * Add a Node and Group to the Topology Info.
 */
int
cc_add_fullnode_group_entry(cluster_config_t * cc, cf_node fullnode ) {
	static char * meth = "add_fullnode_group_entry()";
	int rc = 0;
//	printf("[ENTER]<%s:%s> fullnode(%"PRIx64")\n", MOD, meth, fullnode );

	// Look for the group -- if found, then save the index.
	// And, if not found, add it, and save the index.
	cc_group_t group_id = cc_compute_group_id( fullnode );
	int group_ndx = cc_add_group( cc, group_id );

	// Group is all set.  Now add the node (we shouldn't have one already).
	int node_ndx = cc_add_fullnode( cc, fullnode );

	// Quick validation step -- if the membership array shows a NON-negative
	// entry, point that out, but ALSO
	if( cc->membership[node_ndx]  > 0 && cc->membership[node_ndx] != group_ndx) {
		cf_debug(AS_PARTITION, "[ERROR]<%s:%s>Adding FULLNODE[%d](%"PRIx64") MEMBER(%d) \n",
				MOD, meth, node_ndx, fullnode, cc->membership[node_ndx] );
		rc = -1;
	}

	// Just overwrite the weird case for now -- and we'll figure it out later.
	// TODO: Handle the overwrite error if it ever comes up.  It would probably
	// be ONLY a user error -- but it most likely shows that the user screwed
	// up the config file.
	cc->membership[node_ndx] = group_ndx;
	cc->group_node_count[group_ndx]++; // One more in this group

	return rc;
} // end add_node_group_entry()
Beispiel #6
0
/* cf_svcmsocket_init
 * Initialize a multicast service/receive socket
 * Bind is done to INADDR_ANY - all interfaces
 *  */
int
cf_mcastsocket_init(cf_mcastsocket_cfg *ms)
{
    cf_socket_cfg *s = &(ms->s);

    if (0 > (s->sock = socket(AF_INET, SOCK_DGRAM, 0))) {
        cf_warning(CF_SOCKET, "multicast socket open error: %d %s", errno, cf_strerror(errno));
        return(-1);
    }

    cf_debug(CF_SOCKET, "mcast_socket init: socket %d",s->sock);

    // allows multiple readers on the same address
    uint yes=1;
    if (setsockopt(s->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
        cf_warning(CF_SOCKET, "multicast socket reuse failed: %d %s", errno, cf_strerror(errno));
        return(-1);
    }

    /* Set close-on-exec */
    fcntl(s->sock, F_SETFD, 1);

    // Bind to the incoming port on inaddr any
    memset(&s->saddr, 0, sizeof(s->saddr));
    s->saddr.sin_family = AF_INET;
    s->saddr.sin_addr.s_addr = INADDR_ANY;
    s->saddr.sin_port = htons(s->port);
    if (ms->tx_addr) {
        struct in_addr iface_in;
        memset((char *)&iface_in,0,sizeof(iface_in));
        iface_in.s_addr = inet_addr(ms->tx_addr);

        if(setsockopt(s->sock, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&iface_in, sizeof(iface_in)) == -1) {
            cf_warning(CF_SOCKET, "IP_MULTICAST_IF: %d %s", errno, cf_strerror(errno));
            return(-1);
        }
    }
    unsigned char ttlvar = ms->mcast_ttl;
    if (ttlvar>0) {
        if (setsockopt(s->sock,IPPROTO_IP,IP_MULTICAST_TTL,(char *)&ttlvar,
                       sizeof(ttlvar)) == -1) {
            cf_warning(CF_SOCKET, "IP_MULTICAST_TTL: %d %s", errno, cf_strerror(errno));
        } else {
            cf_info(CF_SOCKET, "setting multicast TTL to be %d",ttlvar);
        }
    }
    while (0 > (bind(s->sock, (struct sockaddr *)&s->saddr, sizeof(struct sockaddr)))) {
        cf_info(CF_SOCKET, "multicast socket bind failed: %d %s", errno, cf_strerror(errno));
    }

    // Register for the multicast group
    inet_pton(AF_INET, s->addr, &ms->ireq.imr_multiaddr.s_addr);
    ms->ireq.imr_interface.s_addr = htonl(INADDR_ANY);
    if (ms->tx_addr) {
        ms->ireq.imr_interface.s_addr = inet_addr(ms->tx_addr);
    }
    setsockopt(s->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&ms->ireq, sizeof(struct ip_mreq));

    return(0);
}
/**
 * Add Node/Group Entry
 * Add a Node and Group to the Topology Info.
 */
int
cc_add_node_group_entry(cluster_config_t *cc, const cc_node_t node,
		const cc_group_t group) {
	int rc = 0;

	// Look for the group -- if found, then save the index.
	// And, if not found, add it, and save the index.
	int group_ndx = cc_add_group(cc, group);

	// Group is all set.  Now add the node (we shouldn't have one already).
	int node_ndx = cc_add_node(cc, node);

	// Quick validation step -- if the membership array shows a NON-negative
	// entry, point that out, but ALSO
	if (cc->membership[node_ndx]  > 0
			&& cc->membership[node_ndx] != group_ndx) {
		cf_debug(AS_PARTITION, "adding node:%d group:%d set:%d",
				node, group, cc->membership[node_ndx]);
		rc = -1;
	}

	// Just overwrite the weird case for now -- and we'll figure it out later.
	// TODO: Handle the overwrite error if it ever comes up.  It would probably
	// be ONLY a user error -- but it most likely shows that the user screwed
	// up the config file.
	cc->membership[node_ndx] = group_ndx;
	cc->group_node_count[group_ndx]++; // One more in this group

	return rc;
} // end add_node_group_entry()
Beispiel #8
0
/**
 * Send failure notification of general UDF execution, but check for special
 * LDT errors and return specific Wire Protocol error codes for these cases:
 * (1) Record not found (2)
 * (2) LDT Collection item not found (125)
 *
 * All other errors get the generic 100 (UDF FAIL) code.
 */
static inline int
send_udf_failure(udf_call *call, const as_string *s)
{
	char *val = as_string_tostring(s);
	size_t vlen = as_string_len((as_string *)s); // TODO - make as_string_len() take const
	long error_code = ldt_get_error_code(val, vlen);

	if (error_code) {

		if (error_code == AS_PROTO_RESULT_FAIL_NOTFOUND ||
			error_code == AS_PROTO_RESULT_FAIL_COLLECTION_ITEM_NOT_FOUND) {

			call->tr->result_code = error_code;
			// Send an "empty" response, with no failure bin.
			as_transaction *    tr          = call->tr;
			single_transaction_response(tr, tr->rsv.ns, NULL/*ops*/,
					NULL /*bin*/, 0 /*nbins*/, 0, 0, NULL, NULL);
			return 0;
		}
	}

	cf_debug(AS_UDF, "Non-special LDT or General UDF Error(%s)", (char *) val);

	call->tr->result_code = AS_PROTO_RESULT_FAIL_UDF_EXECUTION;
	return send_failure(call, as_string_toval(s));
}
Beispiel #9
0
/*
 *  Implementation of the "udf-list" Info. Command.
 */
int udf_cask_info_list(char *name, cf_dyn_buf *out)
{
	cf_debug(AS_UDF, "UDF CASK INFO LIST");

	pthread_mutex_t get_data_mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_cond_t get_data_cond_var = PTHREAD_COND_INITIALIZER;

	udf_get_data_t get_data;
	get_data.db = out;
	get_data.cv = &get_data_cond_var;

	pthread_mutex_lock(&get_data_mutex);

	int retval = as_smd_get_metadata(udf_smd_module_name, "", udf_cask_get_metadata_cb, &get_data);
	if (!retval) {
		if ((retval = pthread_cond_wait(&get_data_cond_var, &get_data_mutex))) {
			cf_warning(AS_UDF, "pthread_cond_wait failed (rv %d)", retval);
		}
	} else {
		cf_warning(AS_UDF, "failed to get UDF metadata (rv %d)", retval);
	} 

	pthread_mutex_unlock(&get_data_mutex);

	pthread_mutex_destroy(&get_data_mutex);
	pthread_cond_destroy(&get_data_cond_var);

	return retval;
}
Beispiel #10
0
static uint32_t
udf_record_ttl(const as_rec * rec)
{
	int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__);
	if (ret) {
		return 0;
	}

	udf_record * urecord = (udf_record *) as_rec_source(rec);


	if (urecord->flag & UDF_RECORD_FLAG_IS_SUBRECORD) {
		cf_debug(AS_UDF, "Return 0 TTL for subrecord ");
		return 0;
	}

	if ((urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN)) {
		uint32_t now = as_record_void_time_get();

		return urecord->r_ref->r->void_time > now ?
				urecord->r_ref->r->void_time - now : 0;
	}
	else {
		cf_info(AS_UDF, "Error in getting ttl: no record found");
		return 0; // since we can't indicate the record doesn't exist
	}
	return 0;
}
Beispiel #11
0
static int
is_connected(int fd)
{
	uint8_t buf[8];
	ssize_t rv = recv(fd, (void*)buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT | MSG_NOSIGNAL);
	
	if (rv == 0) {
		cf_debug("Connected check: Found disconnected fd %d", fd);
		return CONNECTED_NOT;
	}
	
	if (rv < 0) {
		if (errno == EBADF) {
			cf_warn("Connected check: Bad fd %d", fd);
			return CONNECTED_BADFD;
		}
		else if (errno == EWOULDBLOCK || errno == EAGAIN) {
			// The normal case.
			return CONNECTED;
		}
		else {
			cf_info("Connected check: fd %d error %d", fd, errno);
			return CONNECTED_ERROR;
		}
	}
	
	cf_info("Connected check: Peek got unexpected data for fd %d", fd);
	return CONNECTED;
}
Beispiel #12
0
int
citrusleaf_info(char *hostname, short port, char *names, char **values, int timeout_ms)
{
	int rv = -1;
	cf_vector sockaddr_in_v;
	cf_vector_init(&sockaddr_in_v, sizeof( struct sockaddr_in ), 5, 0);
	if (0 != cl_lookup(NULL, hostname, port, &sockaddr_in_v)) {
		cf_debug("Could not find host %s", hostname);
		goto Done;
	}
	
	for (uint i=0; i < cf_vector_size(&sockaddr_in_v) ; i++) 
	{
		struct sockaddr_in  sa_in;
		cf_vector_get(&sockaddr_in_v, i, &sa_in);

		if (0 == citrusleaf_info_host(&sa_in, names, values, timeout_ms, false)) {
			rv = 0;
			goto Done;
		}
	}
	
Done:
	cf_vector_destroy( &sockaddr_in_v );	
	return(rv);
}
Beispiel #13
0
/*
 *  Implementation of the "udf-list" Info. Command.
 */
int udf_cask_info_list(char *name, cf_dyn_buf *out)
{
	cf_debug(AS_UDF, "UDF CASK INFO LIST");

	pthread_mutex_t get_data_mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_cond_t get_data_cond_var = PTHREAD_COND_INITIALIZER;

	udf_get_data_t get_data;
	get_data.db = out;
	get_data.cv = &get_data_cond_var;
	get_data.mt = &get_data_mutex;
	get_data.done = false;

	pthread_mutex_lock(&get_data_mutex);

	int retval = as_smd_get_metadata(udf_smd_module_name, "", udf_cask_get_metadata_cb, &get_data);
	if (!retval) {
		do { // [Note:  Loop protects against spurious wakeups.]
			if ((retval = pthread_cond_wait(&get_data_cond_var, &get_data_mutex))) {
				cf_warning(AS_UDF, "pthread_cond_wait failed (rv %d)", retval);
				break;
			}
		} while (!get_data.done);
	} else {
		cf_warning(AS_UDF, "failed to get UDF metadata (rv %d)", retval);
	}

	pthread_mutex_unlock(&get_data_mutex);

	pthread_mutex_destroy(&get_data_mutex);
	pthread_cond_destroy(&get_data_cond_var);

	return retval;
}
static int
ldt_aerospike_rec_update(const as_aerospike * as, const as_rec * rec)
{
	static const char * meth = "ldt_aerospike_rec_update()";
	if (!as || !rec) {
		cf_warning(AS_LDT, "%s: Invalid Parameters [as=%p, record=%p]... Fail", meth, as, rec);
		return 2;
	}
	cf_detail(AS_LDT, "[ENTER]<%s> as(%p) rec(%p)", meth, as, rec );

	ldt_record *lrecord = (ldt_record *)as_rec_source(rec);
	if (!lrecord) {
		return 2;
	}
	as_rec *h_urec      = lrecord->h_urec;
	as_aerospike *las   = lrecord->as;
	int ret = as_aerospike_rec_update(las, h_urec);
	if (0 == ret) {
		cf_detail(AS_LDT, "<%s> ZERO return(%d) from as_aero_rec_update()", meth, ret );
	} else if (ret == -1) {
		// execution error return as it is
		cf_debug(AS_LDT, "<%s> Exec Error(%d) from as_aero_rec_update()", meth, ret );
	} else if (ret == -2) {
		// Record is not open. Unexpected with LDT usage, though a UDF test case
		// does come through here.
		cf_warning(AS_LDT, "%s: Record does not exist or is not open, cannot update");
	}
	return ret;
}
Beispiel #15
0
/**
 * Set the flags for a specific bin.  This is how LDTs mark Hidden Bins. Other
 * uses may also apply.
 */
static int
udf_record_set_flags(const as_rec * rec, const char * name, uint8_t flags)
{
	int ret = udf_record_param_check(rec, name, __FILE__, __LINE__);
	if (ret) {
		return ret;
	}

	udf_record * urecord = (udf_record *) as_rec_source(rec);
	if (!(urecord->flag & UDF_RECORD_FLAG_ALLOW_UPDATES)) {
		return -1;
	}

	if ( urecord && name ) {
		if (flags & LDT_FLAG_HIDDEN_BIN || flags & LDT_FLAG_LDT_BIN || flags & LDT_FLAG_CONTROL_BIN ) {
			cf_debug(AS_UDF, "LDT flag(%d) Designates Hidden Bin", flags);
			udf_record_cache_sethidden(urecord, name);
		} else {
			cf_warning(AS_UDF, "Unidentified flag setting up %d", flags);
			return -2;
		}
	}

	urecord->flag |= UDF_RECORD_FLAG_METADATA_UPDATED;

	return 0;
}
/*
 * Function to open chunk record
 * Parameters:
 * 		lrd  : Parent ldt record
 * 		keyd : Key digest for the record to be opened
 * 		slot(out): Filled with slot in case of success
 *
 * Return value :
 * 		 0  in case of success returns positive slot value
 * 		-1   in case record is already open
 * 		-2   in case free slot cannot be found
 * 		-3   in case record cannot be opened
 *
 * Description:
 * 		1. Get the empty chunk slot.
 * 		2. Read the record into it
 *
 * Callers:
 *		ldt_aerospike_crec_open
 */
int
crec_open(ldt_record *lrecord, cf_digest *keyd, ldt_slot **lslotp)
{
	cf_detail_digest(AS_LDT, keyd, "[ENTER] crec_open(): Digest: ");

	// 1. Search in opened record
	*lslotp = slot_lookup_by_digest(lrecord, keyd);
	if (*lslotp) {
		cf_debug(AS_LDT, "ldt_aerospike_crec_open : Found already open");
		return 0;
	}

	// 2. Find free slot and setup chunk
	*lslotp     = slot_lookup_free(lrecord, "crec_open");
	if (!*lslotp) {
		return -2;
	}
	slot_init(*lslotp, lrecord);
	slot_setup_digest(*lslotp, keyd);

	// 3. Open Record
	int rv = udf_record_open((udf_record *)as_rec_source((*lslotp)->c_urec_p));
	if (rv) {
		// free the slot for reuse
		slot_destroy(*lslotp, lrecord);
		*lslotp = NULL;
		return -3;
	}
	return 0;
}
Beispiel #17
0
int
as_msg_send_reply(as_file_handle *fd_h, uint32_t result_code, uint32_t generation,
		uint32_t void_time, as_msg_op **ops, as_bin **bins, uint16_t bin_count,
		as_namespace *ns, uint *written_sz, uint64_t trid, const char *setname)
{
	int rv = 0;

	// most cases are small messages - try to stack alloc if we can
	byte fb[MSG_STACK_BUFFER_SZ];
	size_t msg_sz = sizeof(fb);
//	memset(fb,0xff,msg_sz);  // helpful to see what you might not be setting

	uint8_t *msgp = (uint8_t *) as_msg_make_response_msg( result_code, generation,
					void_time, ops, bins, bin_count, ns,
					(cl_msg *)fb, &msg_sz, trid, setname);

	if (!msgp)	return(-1);

	if (fd_h->fd == 0) {
		cf_warning(AS_PROTO, "write to fd 0 internal error");
		cf_crash(AS_PROTO, "send reply: can't write to fd 0");
	}

//	cf_detail(AS_PROTO, "write fd %d",fd);

	size_t pos = 0;
	while (pos < msg_sz) {
		int rv = send(fd_h->fd, msgp + pos, msg_sz - pos, MSG_NOSIGNAL);
		if (rv > 0) {
			pos += rv;
		}
		else if (rv < 0) {
			if (errno != EWOULDBLOCK) {
				// common message when a client aborts
				cf_debug(AS_PROTO, "protocol write fail: fd %d sz %zd pos %zd rv %d errno %d", fd_h->fd, msg_sz, pos, rv, errno);
				as_end_of_transaction_force_close(fd_h);
				rv = -1;
				goto Exit;
			}
			usleep(1); // Yield
		} else {
			cf_info(AS_PROTO, "protocol write fail zero return: fd %d sz %d pos %d ", fd_h->fd, msg_sz, pos);
			as_end_of_transaction_force_close(fd_h);
			rv = -1;
			goto Exit;
		}
	}

	// good for stats as a higher layer
	if (written_sz) *written_sz = msg_sz;

	as_end_of_transaction_ok(fd_h);

Exit:
	if ((uint8_t *)msgp != fb)
		cf_free(msgp);

	return(rv);
}
Beispiel #18
0
/*
 * Reading local directory to get specific module item's contents.
 * In future if needed we can change this to reading from smd metadata. 
 */
int udf_cask_info_get(char *name, char * params, cf_dyn_buf * out) {

	int                 resp                = 0;
	char                filename[128]       = {0};
	int                 filename_len        = sizeof(filename);
	uint8_t *           content             = NULL;
	size_t              content_len         = 0;
	unsigned char       content_gen[256]    = {0};
	uint8_t             udf_type            = AS_UDF_TYPE_LUA;

	cf_debug(AS_INFO, "UDF CASK INFO GET");

	// get (required) script filename
	if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) {
		cf_info(AS_INFO, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
		return 0;
	}

	mod_lua_rdlock(&mod_lua);
	// read the script from filesystem
	resp = file_read(filename, &content, &content_len, content_gen);
	mod_lua_unlock(&mod_lua);
	if ( resp ) {
		switch ( resp ) {
			case 1 : {
				cf_dyn_buf_append_string(out, "error=not_found");
				break;
			}
			case 2 : {
				cf_dyn_buf_append_string(out, "error=empty");
				break;
			}
			default : {
				cf_dyn_buf_append_string(out, "error=unknown_error");
				break; // complier complains without a break;
			}
		}
	}
	else {
		// put back the result
		cf_dyn_buf_append_string(out, "gen=");
		cf_dyn_buf_append_string(out, (char *) content_gen);
		cf_dyn_buf_append_string(out, ";type=");
		cf_dyn_buf_append_string(out, as_udf_type_name[udf_type]);
		cf_dyn_buf_append_string(out, ";content=");
		cf_dyn_buf_append_buf(out, content, content_len);
		cf_dyn_buf_append_string(out, ";");
	}

	if ( content ) {
		cf_free(content);
		content = NULL;
	}

	return 0;
}
Beispiel #19
0
static int
as_node_create_connection(as_node* node, int* fd)
{
	// Create a non-blocking socket.
	*fd = cf_socket_create_nb();
	
	if (*fd == -1) {
		// Local problem - socket create failed.
		cf_debug("Socket create failed for %s", node->name);
		return CITRUSLEAF_FAIL_CLIENT;
	}
	
	// Try primary address.
	as_address* primary = as_vector_get(&node->addresses, node->address_index);
	
	if (cf_socket_start_connect_nb(*fd, &primary->addr) == 0) {
		// Connection started ok - we have our socket.
		return as_node_authenticate_connection(node, fd);
	}
	
	// Try other addresses.
	as_vector* addresses = &node->addresses;
	for (uint32_t i = 0; i < addresses->size; i++) {
		as_address* address = as_vector_get(addresses, i);
		
		// Address points into alias array, so pointer comparison is sufficient.
		if (address != primary) {
			if (cf_socket_start_connect_nb(*fd, &address->addr) == 0) {
				// Replace invalid primary address with valid alias.
				// Other threads may not see this change immediately.
				// It's just a hint, not a requirement to try this new address first.
				cf_debug("Change node address %s %s:%d", node->name, address->name, (int)cf_swap_from_be16(address->addr.sin_port));
				ck_pr_store_32(&node->address_index, i);
				return as_node_authenticate_connection(node, fd);
			}
		}
	}
	
	// Couldn't start a connection on any socket address - close the socket.
	cf_info("Failed to connect: %s %s:%d", node->name, primary->name, (int)cf_swap_from_be16(primary->addr.sin_port));
	cf_close(*fd);
	*fd = -1;
	return CITRUSLEAF_FAIL_UNAVAILABLE;
}
Beispiel #20
0
int udf_cask_info_remove(char *name, char * params, cf_dyn_buf * out) {

	char    filename[128]   = {0};
	int     filename_len    = sizeof(filename);
	char file_path[1024]	= {0};
	struct stat buf;

	cf_debug(AS_INFO, "UDF CASK INFO REMOVE");

	// get (required) script filename
	if ( as_info_parameter_get(params, "filename", filename, &filename_len) ) {
		cf_info(AS_UDF, "invalid or missing filename");
		cf_dyn_buf_append_string(out, "error=invalid_filename");
	}

	// now check if such a file-name exists :
	if (!g_config.mod_lua.user_path)
	{
		return -1;
	}

	snprintf(file_path, 1024, "%s/%s", g_config.mod_lua.user_path, filename);

	cf_debug(AS_INFO, " Lua file removal full-path is : %s \n", file_path);

	if (stat(file_path, &buf) != 0) {
		cf_info(AS_UDF, "failed to read file from : %s, error : %s", file_path, cf_strerror(errno));
		cf_dyn_buf_append_string(out, "error=file_not_found");
		return -1;
	}

	as_smd_delete_metadata(udf_smd_module_name, filename);

	// this is what an error would look like
	//    cf_dyn_buf_append_string(out, "error=");
	//    cf_dyn_buf_append_int(out, resp);

	cf_dyn_buf_append_string(out, "ok");

	cf_info(AS_UDF, "UDF module '%s' (%s) removed", filename, file_path);

	return 0;
}
Beispiel #21
0
int
udf_cask_smd_merge_fn (char *module, as_smd_item_list_t **item_list_out, as_smd_item_list_t **item_lists_in, size_t num_lists, void *udata)
{
	cf_debug(AS_UDF, "UDF CASK merge function");

	// (For now, just send back an empty metadata item list.)
	as_smd_item_list_t *item_list = as_smd_item_list_create(0);
	*item_list_out = item_list;

	return(0);
}
Beispiel #22
0
/* cf_socket_send
 * Send to a socket */
int
cf_socket_send(int sock, void *buf, size_t buflen, int flags)
{
    int i;
    flags |= MSG_NOSIGNAL;
    if (0 >= (i = send(sock, buf, buflen, flags))) {
        cf_debug(CF_SOCKET, "send() failed: %d %s", errno, cf_strerror(errno));
    }

    return(i);
}
Beispiel #23
0
int
cf_ipaddr_get(int socket, char *nic_id, char **node_ip )
{
	struct sockaddr_in sin;
	struct ifreq ifr;
	in_addr_t ip_addr;

	memset(&ip_addr, 0, sizeof(in_addr_t));
	memset(&sin, 0, sizeof(struct sockaddr));
	memset(&ifr, 0, sizeof(ifr));

	// copy the nic name (eth0, eth1, eth2, etc.) ifr variable structure
	strncpy(ifr.ifr_name, nic_id, IFNAMSIZ);

	// get the ifindex for the adapter...
	if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
		cf_debug(CF_MISC, "Can't get ifindex for adapter %s - %d %s\n", nic_id, errno, cf_strerror(errno));
		return(-1);
	}

	// get the IP address
	memset(&sin, 0, sizeof(struct sockaddr));
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, nic_id, IFNAMSIZ);
	ifr.ifr_addr.sa_family = AF_INET;
	if (ioctl(socket, SIOCGIFADDR, &ifr)< 0) {
		cf_debug(CF_MISC, "can't get IP address: %d %s", errno, cf_strerror(errno));
		return(-1);
	}
	memcpy(&sin, &ifr.ifr_addr, sizeof(struct sockaddr));
	ip_addr = sin.sin_addr.s_addr;
	char cpaddr[24];
	if (NULL == inet_ntop(AF_INET, &ip_addr, (char *)cpaddr, sizeof(cpaddr))) {
		cf_warning(CF_MISC, "received suspicious address %s : %s", cpaddr, cf_strerror(errno));
		return(-1);
	}
	cf_info (CF_MISC, "Node ip: %s", cpaddr);
	*node_ip = cf_strdup(cpaddr);

	return(0);
}
Beispiel #24
0
int match_partial_index_name(char *iname)
{
	char tmp_name[TBLD_HASH_KEY_SIZE];
	memset(tmp_name, 0, TBLD_HASH_KEY_SIZE);
	memcpy(tmp_name, iname, strlen(iname));

	long val = -1;
	if(SHASH_OK != shash_get(IndD, (void*)tmp_name, (void*)&val)) {
		cf_debug(AS_SINDEX, "shash get failed on %s", iname);
	}

	return val != -1 ? val - 1 : -1;
}
Beispiel #25
0
/**
 * Set the cache value for a bin, including flags.
 */
static void
udf_record_cache_set(udf_record * urecord, const char * name, as_val * value,
					 bool dirty)
{
	cf_debug(AS_UDF, "[ENTER] urecord(%p) name(%p)[%s] dirty(%d)",
			  urecord, name, name, dirty);

	bool modified = false;

	for ( uint32_t i = 0; i < urecord->nupdates; i++ ) {
		udf_record_bin * bin = &(urecord->updates[i]);

		// bin exists, then we will release old value and set new value.
		if ( strncmp(name, bin->name, AS_ID_BIN_SZ) == 0 ) {
			cf_detail(AS_UDF, "udf_record_set: %s found", name);

			// release previously set value
			as_val_destroy(bin->value);

			// set new value, with dirty flag
			if( value != NULL ) {
				bin->value = (as_val *) value;
			}
			bin->dirty = dirty;
			cf_detail(AS_UDF, "udf_record_set: %s set for %p:%p", name,
					urecord, bin->value);

			modified = true;
			break;
		}
	}

	// If not modified, then we will add the bin to the cache
	if ( ! modified ) {
		if ( urecord->nupdates < UDF_RECORD_BIN_ULIMIT ) {
			udf_record_bin * bin = &(urecord->updates[urecord->nupdates]);
			strncpy(bin->name, name, AS_ID_BIN_SZ);
			bin->value = (as_val *) value;
			bin->dirty = dirty;
			bin->ishidden = false;
			urecord->nupdates++;
			cf_detail(AS_UDF, "udf_record_set: %s not modified, add for %p:%p",
					name, urecord, bin->value);
		}
		else {
			cf_warning(AS_UDF, "UDF bin limit (%d) exceeded (bin %s)",
					UDF_RECORD_BIN_ULIMIT, name);
			urecord->flag |= UDF_RECORD_FLAG_TOO_MANY_BINS;
		}
	}
}
Beispiel #26
0
/**
 * Send failure notification of general UDF execution, but check for special
 * LDT errors and return specific Wire Protocol error codes for these cases:
 * (1) Record not found (2)
 * (2) LDR Collection item not found (125)
 *
 * All other errors get the generic 100 (UDF FAIL) code.
 *
 * Parse (Actually, probe) the error string, and if we see this pattern:
 * FileName:Line# 4digits:LDT-<Error String>
 * For example:
 * .../aerospike-lua-core/src/ldt/lib_llist.lua:982: 0002:LDT-Top Record Not Found
 * All UDF errors (LDT included), have the "filename:line# " prefix, and then
 * LDT errors follow that with a known pattern:
 * (4 digits, colon, LDT-<Error String>).
 * We will check the error string by looking for specific markers after the
 * the space that follows the filename:line#.  If we see the markers, we will
 * parse the LDT error code and use that as the wire protocol error if it is
 * one of the special ones:
 * (1)  "0002:LDT-Top Record Not Found"
 * (2)  "0125:LDT-Item Not Found"
 */
static inline int
send_udf_failure(udf_call *call, int vtype, void *val, size_t vlen)
{
	// We need to do a quick look to see if this is an LDT error string.  If it
	// is, then we'll look deeper.  We start looking after the first space.
	char * charptr;
	char * valptr = (char *) val;
	long error_code;

	// Start with the space, if it exists, as the marker for where we start
	// looking for the LDT error contents.
	if ((charptr = strchr((const char *) val, ' ')) != NULL) {
		// We must be at least 10 chars from the end, so if we're less than that
		// we are obviously not looking at an LDT error.
		if (&charptr[9] < &valptr[vlen]) {
			if (memcmp(&charptr[5], ":LDT-", 5) == 0) {
				error_code = strtol(&charptr[1], NULL, 10);
				if (error_code == AS_PROTO_RESULT_FAIL_NOTFOUND ||
					error_code == AS_PROTO_RESULT_FAIL_COLLECTION_ITEM_NOT_FOUND)
				{
					call->transaction->result_code = error_code;
					cf_debug(AS_UDF, "LDT Error: Code(%ld) String(%s)",
							error_code, (char *) val);
					// Send an "empty" response, with no failure bin.
					as_transaction *    tr          = call->transaction;
					single_transaction_response(tr, tr->rsv.ns, NULL/*ops*/,
							NULL /*bin*/, 0 /*nbins*/, 0, 0, NULL, NULL);
					return 0;
				}
			}
		}
	}

	cf_debug(AS_UDF, "Non-special LDT or General UDF Error(%s)", (char *) val);

	call->transaction->result_code = AS_PROTO_RESULT_FAIL_UDF_EXECUTION;
	return send_response(call, "FAILURE", 7, vtype, val, vlen);
}
Beispiel #27
0
bool
udf_timer_timedout(const as_timer *as_tt)
{
	time_tracker *tt = (time_tracker *)pthread_getspecific(timer_tlskey);
	if (!tt || !tt->end_time || !tt->udata) {
		return true;
	}
	bool timedout = (cf_getms() > tt->end_time(tt));
	if (timedout) {
		cf_debug(AS_UDF, "UDF Timed Out [%ld:%ld]", cf_getms(), tt->end_time(tt));
		return true;
	}
	return false;
}
/*
 * Check and validate parameter before performing operation
 *
 * return:
 *      UDF_ERR * in case of failure
 *      0 in case of success
 */
static int
udf_aerospike_param_check(const as_aerospike *as, const as_rec *rec, char *fname, int lineno)
{
	if (!as) {
		cf_debug(AS_UDF, "Invalid Paramters: aerospike=%p", as);
		return UDF_ERR_INTERNAL_PARAMETER;
	}

	int ret = udf_record_param_check(rec, UDF_BIN_NONAME, fname, lineno);
	if (ret) {
		return ret;
	}
	return 0;
}
Beispiel #29
0
int
as_netio_send_packet(as_file_handle *fd_h, cf_buf_builder *bb_r, uint32_t *offset, bool blocking)
{
#if defined(USE_SYSTEMTAP)
	uint64_t nodeid = g_config.self_node;
#endif

	uint32_t len  = bb_r->used_sz;
	uint8_t *buf  = bb_r->buf;

	as_proto proto;
	proto.version = PROTO_VERSION;
	proto.type    = PROTO_TYPE_AS_MSG;
	proto.sz      = len - 8;
	as_proto_swap(&proto);

    memcpy(bb_r->buf, &proto, 8); 

	uint32_t pos = *offset;

	ASD_QUERY_SENDPACKET_STARTING(nodeid, pos, len);

	int rv;
	int retry = 0;
	cf_detail(AS_PROTO," Start At %p %d %d", buf, pos, len);
	while (pos < len) {
		rv = send(fd_h->fd, buf + pos, len - pos, MSG_NOSIGNAL);
		if (rv <= 0) {
			if (errno != EAGAIN) {
				cf_debug(AS_PROTO, "Packet send response error returned %d errno %d fd %d", rv, errno, fd_h->fd);
				return AS_NETIO_IO_ERR;
			}
			if (!blocking && (retry > AS_NETIO_MAX_IO_RETRY)) {
				*offset = pos;
				cf_detail(AS_PROTO," End At %p %d %d", buf, pos, len);
				ASD_QUERY_SENDPACKET_CONTINUE(nodeid, pos);
				return AS_NETIO_CONTINUE;
			}
			retry++;
			// bigger packets so try few extra times 
			usleep(100);
		}
		else {
			pos += rv;
		}
	}
	ASD_QUERY_SENDPACKET_FINISHED(nodeid);
	return AS_NETIO_OK;
}
Beispiel #30
0
/*
 * Function: Get bin value from cached copy. All the update in a
 *           commit window is not applied to the record directly
 *           but maintained in-memory cache. This function used
 *           to retrieve cached value
 *
 *           Similar function for get and free of cache
 *
 * Parameters:
 * 		urec    : Parent ldt record
 *
 * Return value :
 * 		value  (as_val) in case of success [for get]
 * 		NULL  in case of failure
 * 		set and free return Nothing
 *
 * Callers:
 * 		GET and SET
 * 		udf_record_get
 * 		udf_record_set
 * 		udf_record_remove
 *
 * 		FREE
 * 		udf_aerospike__execute_updates (when crossing commit window)
 * 		ldt_aerospike_crec_close       (when closing chunk sub record)
 * 		udf_record_close               (finally closing record/generally subrecord)
 * 		udf_rw_commit                  (commit the udf record or parent ldt record)
 *
 *		ldt_aerospike_crec_create
 */
static as_val *
udf_record_cache_get(udf_record * urecord, const char * name)
{
	cf_debug(AS_UDF, "[ENTER] BinName(%s) ", name );
	if ( urecord->nupdates > 0 ) {
		cf_detail(AS_UDF, "udf_record_get: %s find", name);
		for ( uint32_t i = 0; i < urecord->nupdates; i++ ) {
			udf_record_bin * bin = &(urecord->updates[i]);
			if ( strncmp(name, bin->name, AS_ID_BIN_SZ) == 0 ) {
				cf_detail(AS_UDF, "Bin %s found, type(%d)", name, bin->value->type );
				return bin->value; // note it's OK if the bin contains a nil
			}
		}
	}
	return NULL;
}