static as_status as_parse_roles(as_error* err, uint8_t* buffer, size_t size, as_vector* /*<as_role*>*/ roles) { uint8_t* p = buffer; uint8_t* end = buffer + size; as_role* role; char role_name[AS_ROLE_SIZE]; int len; int sz; uint8_t id; uint8_t field_count; uint8_t result; while (p < end) { result = p[1]; if (result != 0) { return result; } field_count = p[3]; p += HEADER_REMAINING; role_name[0] = 0; role = 0; for (uint8_t b = 0; b < field_count; b++) { len = cf_swap_from_be32(*(int*)p); p += 4; id = *p++; len--; if (id == ROLE) { sz = (len <= (AS_ROLE_SIZE-1))? len : (AS_ROLE_SIZE-1); memcpy(role_name, p, sz); role_name[sz] = 0; p += len; } else if (id == PRIVILEGES) { p = as_parse_privileges(p, &role); } else { p += len; } } if (role_name[0] == 0 && role == 0) { continue; } if (! role) { role = cf_malloc(sizeof(as_role)); role->privileges_size = 0; } strcpy(role->name, role_name); as_vector_append(roles, &role); } return AEROSPIKE_OK; }
static as_status as_parse_users(as_error* err, uint8_t* buffer, size_t size, as_vector* /*<as_user*>*/ users) { uint8_t* p = buffer; uint8_t* end = buffer + size; as_user* user; char user_name[AS_USER_SIZE]; int len; int sz; uint8_t id; uint8_t field_count; uint8_t result; while (p < end) { result = p[1]; if (result != 0) { return result; } field_count = p[3]; p += HEADER_REMAINING; user_name[0] = 0; user = 0; for (uint8_t b = 0; b < field_count; b++) { len = cf_swap_from_be32(*(int*)p); p += 4; id = *p++; len--; if (id == USER) { sz = (len <= (AS_USER_SIZE-1))? len : (AS_USER_SIZE-1); memcpy(user_name, p, sz); user_name[sz] = 0; p += len; } else if (id == ROLES) { p = as_parse_users_roles(p, &user); } else { p += len; } } if (user_name[0] == 0 && user == 0) { continue; } if (! user) { user = cf_malloc(sizeof(as_user)); user->roles_size = 0; } strcpy(user->name, user_name); as_vector_append(users, &user); } return 0; }
void as_node_add_address(as_node* node, struct sockaddr_in* addr) { as_address address; address.addr = *addr; as_socket_address_name(addr, address.name); as_vector_append(&node->addresses, &address); }
void as_seeds_update(as_cluster* cluster, as_seed* seed_list, uint32_t size) { as_seeds* seeds = seeds_create(seed_list, size); as_seeds* old = swap_seeds(cluster, seeds); as_gc_item item; item.data = old; item.release_fn = gc_seeds; as_vector_append(cluster->gc, &item); }
static void as_cluster_find_nodes_to_add(as_cluster* cluster, as_vector* /* <as_host> */ friends, as_vector* /* <as_node*> */ nodes_to_add) { as_error err; as_error_init(&err); as_vector addresses; as_vector_inita(&addresses, sizeof(struct sockaddr_in), 5); as_node_info node_info; for (uint32_t i = 0; i < friends->size; i++) { as_host* friend = as_vector_get(friends, i); as_vector_clear(&addresses); as_status status = as_lookup(&err, friend->name, friend->port, &addresses); if (status != AEROSPIKE_OK) { as_log_warn("%s %s", as_error_string(status), err.message); continue; } for (uint32_t i = 0; i < addresses.size; i++) { struct sockaddr_in* addr = as_vector_get(&addresses, i); status = as_lookup_node(cluster, &err, addr, &node_info); if (status == AEROSPIKE_OK) { as_node* node = as_cluster_find_node(cluster->nodes, nodes_to_add, node_info.name); if (node) { // Duplicate node name found. This usually occurs when the server // services list contains both internal and external IP addresses // for the same node. Add new host to list of alias filters // and do not add new node. as_close(node_info.fd); as_address* a = as_node_get_address_full(node); as_log_info("Node %s:%d already exists with nodeid %s and address %s:%d", friend->name, friend->port, node->name, a->name, (int)cf_swap_from_be16(a->addr.sin_port)); node->friends++; as_node_add_address(node, friend, addr); continue; } node = as_node_create(cluster, friend, addr, &node_info); as_address* a = as_node_get_address_full(node); as_log_info("Add node %s %s:%d", node_info.name, a->name, (int)cf_swap_from_be16(a->addr.sin_port)); as_vector_append(nodes_to_add, &node); } else { as_log_warn("Failed to connect to friend %s:%d. %s %s", friend->name, friend->port, as_error_string(status), err.message); } }
bool as_vector_append_unique(as_vector* vector, void* value) { char* item = vector->list; for (uint32_t i = 0; i < vector->size; i++) { if (memcmp(item, value, vector->item_size) == 0) { return false; } item += vector->item_size; } as_vector_append(vector, value); return true; }
void as_seeds_add(as_cluster* cluster, as_seed* seed_list, uint32_t size) { as_seeds* current = as_seeds_reserve(cluster); as_seed concat[current->size + size]; as_seed* src = current->array; as_seed* trg = concat; for (uint32_t i = 0; i < current->size; i++) { trg->name = src->name; trg->port = src->port; src++; trg++; } uint32_t dups = 0; src = seed_list; for (uint32_t i = 0; i < size; i++) { if (as_find_seed(cluster, src->name, src->port)) { as_log_debug("Duplicate seed %s:%d", src->name, src->port); dups++; continue; } as_log_debug("Add seed %s:%d", src->name, src->port); trg->name = src->name; trg->port = src->port; src++; trg++; } as_seeds_release(current); as_seeds* seeds = seeds_create(concat, current->size + size - dups); as_seeds* old = swap_seeds(cluster, seeds); as_gc_item item; item.data = old; item.release_fn = gc_seeds; as_vector_append(cluster->gc, &item); }
/** * Add nodes using copy on write semantics. */ void as_cluster_add_nodes_copy(as_cluster* cluster, as_vector* /* <as_node*> */ nodes_to_add) { // Create temporary nodes array. as_nodes* nodes_old = cluster->nodes; as_nodes* nodes_new = as_nodes_create(nodes_old->size + nodes_to_add->size); // Add existing nodes. memcpy(nodes_new->array, nodes_old->array, sizeof(as_node*) * nodes_old->size); // Add new nodes. memcpy(&nodes_new->array[nodes_old->size], nodes_to_add->list, sizeof(as_node*) * nodes_to_add->size); // Replace nodes with copy. set_nodes(cluster, nodes_new); // Put old nodes on garbage collector stack. as_gc_item item; item.data = nodes_old; item.release_fn = (as_release_fn)release_nodes; as_vector_append(cluster->gc, &item); }
static as_status as_cluster_seed_nodes(as_cluster* cluster, as_error* err, bool enable_warnings) { // Add all nodes at once to avoid copying entire array multiple times. as_vector nodes_to_add; as_vector_inita(&nodes_to_add, sizeof(as_node*), 64); as_vector addresses; as_vector_inita(&addresses, sizeof(struct sockaddr_in), 5); as_node_info node_info; as_error error_local; as_error_init(&error_local); // AEROSPIKE_ERR_TIMEOUT doesn't come with a message; make sure it's initialized. as_status status = AEROSPIKE_OK; as_seeds* seeds = as_seeds_reserve(cluster); for (uint32_t i = 0; i < seeds->size; i++) { as_seed* seed = &seeds->array[i]; as_vector_clear(&addresses); status = as_lookup(&error_local, seed->name, seed->port, &addresses); if (status != AEROSPIKE_OK) { if (enable_warnings) { as_log_warn("Failed to lookup %s:%d. %s %s", seed->name, seed->port, as_error_string(status), error_local.message); } continue; } for (uint32_t i = 0; i < addresses.size; i++) { struct sockaddr_in* addr = as_vector_get(&addresses, i); status = as_lookup_node(cluster, &error_local, addr, &node_info); if (status == AEROSPIKE_OK) { as_host host; if (as_strncpy(host.name, seed->name, sizeof(host.name))) { as_log_warn("Hostname has been truncated: %s", host.name); } host.port = seed->port; as_node* node = as_cluster_find_node_in_vector(&nodes_to_add, node_info.name); if (node) { as_close(node_info.fd); as_node_add_address(node, &host, addr); } else { node = as_node_create(cluster, &host, addr, &node_info); as_address* a = as_node_get_address_full(node); as_log_info("Add node %s %s:%d", node->name, a->name, (int)cf_swap_from_be16(a->addr.sin_port)); as_vector_append(&nodes_to_add, &node); } } else { if (enable_warnings) { as_log_warn("Failed to connect to seed %s:%d. %s %s", seed->name, seed->port, as_error_string(status), error_local.message); } } } } as_seeds_release(seeds); if (nodes_to_add.size > 0) { as_cluster_add_nodes(cluster, &nodes_to_add); status = AEROSPIKE_OK; } else { status = as_error_set_message(err, AEROSPIKE_ERR_CLIENT, "Failed to seed cluster"); } as_vector_destroy(&nodes_to_add); as_vector_destroy(&addresses); return status; }
/** * @return AEROSPIKE_OK if successful. Otherwise an error occurred. */ as_status aerospike_udf_list( aerospike * as, as_error * err, const as_policy_info * policy, as_udf_files * files) { as_error_reset(err); if (! policy) { policy = &as->config.policies.info; } char* response = 0; as_status status = aerospike_info_any(as, err, policy, "udf-list", &response); if (status) { return status; } // response := udf-list\tfilename=<name>,hash=<hash>,type=<type>;[filename=<name>...] char* p = strchr(response, '\t'); if (!p) { as_error_update(err, AEROSPIKE_ERR_PARAM, "Invalid udf-list response: %s", response); free(response); return AEROSPIKE_ERR_PARAM; } p++; uint32_t capacity = (files->capacity <= 0) ? 500 : files->capacity; as_vector ptrs; as_vector_inita(&ptrs, sizeof(as_udf_file_ptr), capacity); as_udf_file_ptr ptr = {0,0,0}; char* token = p; while (*p) { switch (*p) { case '=': *p++ = 0; as_udf_parse_file(token, p, &ptr); break; case ',': *p++ = 0; token = p; break; case ';': *p++ = 0; token = p; as_vector_append(&ptrs, &ptr); ptr.name = 0; ptr.hash = 0; ptr.type = 0; break; default: p++; break; } } if (files->capacity == 0 && files->entries == NULL) { as_udf_files_init(files, ptrs.size); } uint32_t limit = ptrs.size < files->capacity ? ptrs.size : files->capacity; files->size = limit; for (uint32_t i = 0; i < limit; i++) { as_udf_file_ptr* ptr = as_vector_get(&ptrs, i); as_udf_file* file = &files->entries[i]; if (ptr->name) { as_strncpy(file->name, ptr->name, AS_UDF_FILE_NAME_SIZE); } else { file->name[0] = 0; } if (ptr->hash) { // The hash is not null terminated, so normal strncpy is appropriate here. // strncpy will also pad zeroes if hash size is incorrect. strncpy((char*)file->hash, ptr->hash, AS_UDF_FILE_HASH_SIZE); } else { file->hash[0] = 0; } file->type = AS_UDF_TYPE_LUA; file->content._free = false; file->content.size = 0; file->content.capacity = 0; file->content.bytes = NULL; } as_vector_destroy(&ptrs); free(response); return AEROSPIKE_OK; }