// This will find the library and UUID tags of the sub effect pointed by the // node, gets the effect descriptor and lib_entry_t and adds the subeffect - // sub_entry_t to the gSubEffectList int addSubEffect(cnode *root) { ALOGV("addSubEffect"); cnode *node; effect_uuid_t uuid; effect_descriptor_t *d; lib_entry_t *l; list_elem_t *e; node = config_find(root, LIBRARY_TAG); if (node == NULL) { return -EINVAL; } l = getLibrary(node->value); if (l == NULL) { ALOGW("addSubEffect() could not get library %s", node->value); return -EINVAL; } node = config_find(root, UUID_TAG); if (node == NULL) { return -EINVAL; } if (stringToUuid(node->value, &uuid) != 0) { ALOGW("addSubEffect() invalid uuid %s", node->value); return -EINVAL; } d = malloc(sizeof(effect_descriptor_t)); if (l->desc->get_descriptor(&uuid, d) != 0) { char s[40]; uuidToString(&uuid, s, 40); ALOGW("Error querying effect %s on lib %s", s, l->name); free(d); return -EINVAL; } #if (LOG_NDEBUG==0) char s[256]; dumpEffectDescriptor(d, s, 256); ALOGV("addSubEffect() read descriptor %p:%s",d, s); #endif if (EFFECT_API_VERSION_MAJOR(d->apiVersion) != EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) { ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name); free(d); return -EINVAL; } sub_effect_entry_t *sub_effect = malloc(sizeof(sub_effect_entry_t)); sub_effect->object = d; // lib_entry_t is stored since the sub effects are not linked to the library sub_effect->lib = l; e = malloc(sizeof(list_elem_t)); e->object = sub_effect; e->next = gSubEffectList->sub_elem; gSubEffectList->sub_elem = e; ALOGV("addSubEffect end"); return 0; }
ConfigEntry* config_push(const char* variable,const char* value) { ConfigEntry* e; e = config_find(variable); if(!e) { if(confListPtr > CONF_ENTRIES_COUNT-1) return NULL; e = &confList[confListPtr++]; e->variableLength = strlen(variable); if(!e->variableLength) { --confListPtr; return NULL; } e->valueLength = strlen(value); strcpy(e->variable,variable); strcpy(e->value,value); } else { //just update e->valueLength = strlen(value); strcpy(e->value,value); } return e; }
/* * config_isolation -- * Isolation configuration. */ static void config_isolation(void) { CONFIG *cp; const char *cstr; /* * Isolation: choose something if isolation wasn't specified. */ cp = config_find("isolation", strlen("isolation")); if (!(cp->flags & C_PERM)) { /* Avoid "maybe uninitialized" warnings. */ switch (MMRAND(1, 4)) { case 1: cstr = "isolation=random"; break; case 2: cstr = "isolation=read-uncommitted"; break; case 3: cstr = "isolation=read-committed"; break; case 4: default: cstr = "isolation=snapshot"; break; } config_single(cstr, 0); } }
/* * config_find_is_perm * Return if a specific configuration entry was permanently set. */ static int config_find_is_perm(const char *s, size_t len) { CONFIG *cp; cp = config_find(s, len); return (cp->flags & C_PERM ? 1 : 0); }
/* * config_compression -- * Compression configuration. */ static void config_compression(void) { CONFIG *cp; const char *cstr; /* * Compression: choose something if compression wasn't specified, * otherwise confirm the appropriate shared library is available. * We don't include LZO in the test compression choices, we don't * yet have an LZO module of our own. */ cp = config_find("compression", strlen("compression")); if (!(cp->flags & C_PERM)) { cstr = "compression=none"; switch (MMRAND(1, 10)) { case 1: case 2: case 3: /* 30% */ break; case 4: case 5: /* 20% */ if (access(BZIP_PATH, R_OK) == 0) cstr = "compression=bzip"; break; case 6: /* 10% */ if (access(BZIP_PATH, R_OK) == 0) cstr = "compression=bzip-raw"; break; case 7: case 8: /* 20% */ if (access(SNAPPY_PATH, R_OK) == 0) cstr = "compression=snappy"; break; case 9: case 10: /* 20% */ if (access(ZLIB_PATH, R_OK) == 0) cstr = "compression=zlib"; break; } config_single(cstr, 0); } switch (g.c_compression_flag) { case COMPRESS_BZIP: case COMPRESS_BZIP_RAW: if (access(BZIP_PATH, R_OK) != 0) die(0, "bzip library not found or not readable"); break; case COMPRESS_LZO: if (access(LZO_PATH, R_OK) != 0) die(0, "LZO library not found or not readable"); break; case COMPRESS_SNAPPY: if (access(SNAPPY_PATH, R_OK) != 0) die(0, "snappy library not found or not readable"); break; case COMPRESS_ZLIB: if (access(ZLIB_PATH, R_OK) != 0) die(0, "zlib library not found or not readable"); break; } }
char* config_getS(const char* variable) { ConfigEntry* e; e = config_find(variable); if(!e) return NULL; return e->value; }
ConfigEntry* config_replaceS(const char* variable,const char* newValue) { ConfigEntry* e; e = config_find(variable); if(!e) return NULL; e->valueLength = strlen(newValue); strcpy(e->value,newValue); return e; }
/* * config_single -- * Set a single configuration structure value. */ void config_single(const char *s, int perm) { CONFIG *cp; const char *ep; if ((ep = strchr(s, '=')) == NULL) { fprintf(stderr, "%s: %s: illegal configuration value\n", g.progname, s); exit(EXIT_FAILURE); } cp = config_find(s, (size_t)(ep - s)); cp->flags |= perm ? C_PERM : C_TEMP; ++ep; if (cp->flags & C_STRING) { if (strncmp(s, "data_source", strlen("data_source")) == 0 && strncmp("file", ep, strlen("file")) != 0 && strncmp("table", ep, strlen("table")) != 0 && strncmp("lsm", ep, strlen("lsm")) != 0) { fprintf(stderr, "Invalid data source option: %s\n", ep); exit(EXIT_FAILURE); } if (strncmp(s, "file_type", strlen("file_type")) == 0) *cp->vstr = strdup( config_file_type(config_translate(ep))); else *cp->vstr = strdup(ep); if (*cp->vstr == NULL) syserr("Config string parsing"); return; } *cp->v = config_translate(ep); if (cp->flags & C_BOOL) { if (*cp->v != 0 && *cp->v != 1) { fprintf(stderr, "%s: %s: value of boolean not 0 or 1\n", g.progname, s); exit(EXIT_FAILURE); } } else if (*cp->v < cp->min || *cp->v > cp->max) { fprintf(stderr, "%s: %s: value of %" PRIu32 " outside min/max values of %" PRIu32 "-%" PRIu32 "\n", g.progname, s, *cp->v, cp->min, cp->max); exit(EXIT_FAILURE); } }
int loadLibraries(cnode *root) { cnode *node; node = config_find(root, LIBRARIES_TAG); if (node == NULL) { return -ENOENT; } node = node->first_child; while (node) { loadLibrary(node, node->name); node = node->next; } return 0; }
int loadEffects(cnode *root) { cnode *node; node = config_find(root, EFFECTS_TAG); if (node == NULL) { return -ENOENT; } node = node->first_child; while (node) { loadEffect(node); node = node->next; } return 0; }
static void load_output(cnode *root, void *platform, struct listnode *streams_output_cfg_list) { cnode *node = config_find(root, OUTPUTS_TAG); if (node == NULL) { ALOGE("%s: could not load output, node is NULL", __func__); return; } node = node->first_child; while (node) { ALOGV("%s: loading output %s", __func__, node->name); update_streams_output_cfg_list(node, platform, streams_output_cfg_list); node = node->next; } }
int config_getI(const char* variable) { const char* str; const char* base; int result = 0; unsigned char neg = 0; ConfigEntry* e; e = config_find(variable); if(!e) return 0; str = base = e->value; while(*str) { if(!isSpace(*str)) break; ++str; } if(str[0] == '0') return 0; else if(str[0] == '-') { ++str; neg = 1; } while(*str) { if(str - base > 9) break; else if(!isNumerical(*str)) break; result = (result * 10) + (*str - '0'); str++; } if(neg) result *= -1; return result; }
static int snapshot_sync(struct volume *v) { struct file_header sentinel, conf; int next, block = 0; uint32_t seq; next = snapshot_next_free(v, &seq); block = config_find(v, &conf, &sentinel); if (is_config(&conf) && conf.seq != seq) { conf.magic = 0; volume_erase(v, next * v->block_size, 2 * v->block_size); } if (is_config(&sentinel) && (sentinel.seq != seq)) { sentinel.magic = 0; volume_erase(v, block * v->block_size, v->block_size); } if (!is_config(&conf) && !is_config(&sentinel)) { // ULOG_ERR("no config found\n"); } else if (((is_config(&conf) && is_config(&sentinel)) && (memcmp(conf.md5, sentinel.md5, sizeof(conf.md5)) || (conf.seq != sentinel.seq))) || (is_config(&conf) && !is_config(&sentinel))) { uint32_t seq; int next = snapshot_next_free(v, &seq); int ret = snapshot_read_file(v, next, "/tmp/config.tar.gz", CONF); if (ret > 0) { if (sentinel_write(v, conf.seq)) ULOG_ERR("failed to write sentinel data"); } } else if (!is_config(&conf) && is_config(&sentinel) && next) { int ret = snapshot_read_file(v, block, "/tmp/config.tar.gz", CONF); if (ret > 0) if (volatile_write(v, sentinel.seq)) ULOG_ERR("failed to write sentinel data"); } else ULOG_INFO("config in sync\n"); unlink("/tmp/config.tar.gz"); return 0; }
/* * config_checksum -- * Checksum configuration. */ static void config_checksum(void) { CONFIG *cp; /* Choose a checksum mode if nothing was specified. */ cp = config_find("checksum", strlen("checksum")); if (!(cp->flags & C_PERM)) switch (MMRAND(1, 10)) { case 1: /* 10% */ config_single("checksum=on", 0); break; case 2: /* 10% */ config_single("checksum=off", 0); break; default: /* 80% */ config_single("checksum=uncompressed", 0); break; } }
unsigned long pi_configlock_event_load_old (plugin_user_t * user, void *dummy, unsigned long event, buffer_t * token) { FILE *fp; unsigned long l; char buffer[1024], *c; configlock_t *lock; config_element_t *elem; while (locklist) { lock = locklist; locklist = locklist->next; free (lock); } config_load_old (filename); fp = fopen (filename, "r"); if (!fp) return PLUGIN_RETVAL_CONTINUE; while (fgets (buffer, 1024, fp)) { for (c = buffer; *c && *c != ' '; c++); if (!*c) continue; *c++ = '\0'; elem = config_find (buffer); if (!elem) continue; lock = malloc (sizeof (configlock_t)); memset (lock, 0, sizeof (configlock_t)); lock->elem = elem; strncpy (lock->name, elem->name, CONFIG_NAMELENGTH); switch (elem->type) { case CFG_ELEM_PTR: sscanf (c, "%p", &lock->data.v_ptr); break; case CFG_ELEM_LONG: sscanf (c, "%ld", &lock->data.v_long); break; case CFG_ELEM_ULONG: case CFG_ELEM_CAP: case CFG_ELEM_MEMSIZE: sscanf (c, "%lu", &lock->data.v_ulong); break; case CFG_ELEM_BYTESIZE: case CFG_ELEM_ULONGLONG: #ifndef USE_WINDOWS sscanf (c, "%Lu", &lock->data.v_ulonglong); #else sscanf (c, "%I64u", &lock->data.v_ulonglong); #endif break; case CFG_ELEM_INT: sscanf (c, "%d", &lock->data.v_int); break; case CFG_ELEM_UINT: sscanf (c, "%u", &lock->data.v_uint); break; case CFG_ELEM_DOUBLE: sscanf (c, "%lf", &lock->data.v_double); break; case CFG_ELEM_STRING: if (lock->data.v_string) free (lock->data.v_string); l = strlen (c); if (c[l - 1] == '\n') c[l-- - 1] = '\0'; if ((*c == '"') && (c[l - 1] == '"')) { c[l - 1] = '\0'; c++; }; lock->data.v_string = string_unescape (c); break; case CFG_ELEM_IP: { #ifdef HAVE_INET_NTOA struct in_addr ia; if (inet_aton (c, &ia)) lock->data.v_ip = ia.s_addr; #else #warning "inet_ntoa not support. Support for CFG_ELEM_IP disabled." #endif break; } } lock->next = locklist; locklist = lock; } fclose (fp); return PLUGIN_RETVAL_CONTINUE; }
unsigned long pi_configlock_event_load (plugin_user_t * user, void *dummy, unsigned long event, void *arg) { FILE *fp; configlock_t *lock; config_element_t *elem; xml_node_t *base, *node; if (!arg) goto leave; while (locklist) { lock = locklist; locklist = locklist->next; free (lock); } fp = fopen ("configlock.xml", "r"); if (!fp) goto leave; base = xml_read (fp); if (!base) { fclose (fp); goto leave; } if (strcmp (base->name, HUBSOFT_NAME)) { xml_free (base); goto leave; } config_load (base); node = xml_node_find (base, "Config"); for (node = node->children; node; node = xml_next (node)) { elem = config_find (node->name); if (!elem) continue; lock = malloc (sizeof (configlock_t)); memset (lock, 0, sizeof (configlock_t)); lock->elem = elem; strncpy (lock->name, elem->name, CONFIG_NAMELENGTH); xml_node_get (node, elem->type, &lock->data.v_ptr); lock->next = locklist; locklist = lock; } xml_free (base); fclose (fp); return PLUGIN_RETVAL_CONTINUE; leave: return pi_configlock_event_load_old (user, dummy, event, NULL); }
/* * config_single -- * Set a single configuration structure value. */ void config_single(const char *s, int perm) { CONFIG *cp; int v; const char *ep; if ((ep = strchr(s, '=')) == NULL) { fprintf(stderr, "%s: %s: illegal configuration value\n", g.progname, s); exit(EXIT_FAILURE); } cp = config_find(s, (size_t)(ep - s)); cp->flags |= perm ? C_PERM : C_TEMP; ++ep; if (cp->flags & C_STRING) { if (strncmp(s, "data_source", strlen("data_source")) == 0 && strncmp("file", ep, strlen("file")) != 0 && strncmp("helium", ep, strlen("helium")) != 0 && strncmp("kvsbdb", ep, strlen("kvsbdb")) != 0 && strncmp("lsm", ep, strlen("lsm")) != 0 && strncmp("table", ep, strlen("table")) != 0) { fprintf(stderr, "Invalid data source option: %s\n", ep); exit(EXIT_FAILURE); } if (strncmp(s, "checksum", strlen("checksum")) == 0) { config_map_checksum(ep, &g.c_checksum_flag); *cp->vstr = strdup(ep); } else if (strncmp( s, "compression", strlen("compression")) == 0) { config_map_compression(ep, &g.c_compression_flag); *cp->vstr = strdup(ep); } else if (strncmp(s, "file_type", strlen("file_type")) == 0) { config_map_file_type(ep, &g.type); *cp->vstr = strdup(config_file_type(g.type)); } else *cp->vstr = strdup(ep); if (*cp->vstr == NULL) syserr("malloc"); return; } v = atoi(ep); if (cp->flags & C_BOOL) { if (v != 0 && v != 1) { fprintf(stderr, "%s: %s: value of boolean not 0 or 1\n", g.progname, s); exit(EXIT_FAILURE); } } else if (v < 0 || (u_int)v < cp->min || (u_int)v > cp->maxset) { fprintf(stderr, "%s: %s: value of %" PRIu32 " outside min/max values of %" PRIu32 "-%" PRIu32 "\n", g.progname, s, *cp->v, cp->min, cp->maxset); exit(EXIT_FAILURE); } *cp->v = (u_int)v; }
/* * config_setup -- * Initialize configuration for a run. */ void config_setup(void) { CONFIG *cp; /* Clear any temporary values. */ config_clear(); /* * Choose a data source type and a file type: they're interrelated (LSM * trees are only compatible with row-store) and other items depend on * them. */ if (!config_find_is_perm("data_source", strlen("data_source"))) switch (MMRAND(0, 2)) { case 0: config_single("data_source=file", 0); break; case 1: #if 0 config_single("data_source=lsm", 0); break; #endif case 2: config_single("data_source=table", 0); break; } if (!config_find_is_perm("file_type", strlen("file_type"))) { if (strcmp(g.c_data_source, "lsm") == 0) config_single("file_type=row", 0); else switch (MMRAND(0, 2)) { case 0: config_single("file_type=fix", 0); break; case 1: config_single("file_type=var", 0); break; case 2: config_single("file_type=row", 0); break; } } g.type = config_translate(g.c_file_type); /* * If data_source and file_type were both "permanent", we may still * have a mismatch. */ if (g.type != ROW && strcmp(g.c_data_source, "lsm") == 0) { fprintf(stderr, "%s: lsm data_source is only compatible with row file_type\n", g.progname); exit(EXIT_FAILURE); } /* Build the object name. */ if ((g.uri = malloc( strlen(g.c_data_source) + strlen(WT_NAME) + 2)) == NULL) syserr("malloc"); strcpy(g.uri, g.c_data_source); strcat(g.uri, ":"); strcat(g.uri, WT_NAME); /* Default single-threaded half of the time. */ cp = config_find("threads", strlen("threads")); if (!(cp->flags & C_PERM)) *cp->v = MMRAND(0, 1) ? 1: CONF_RAND(cp); /* Fill in random values for the rest of the run. */ for (cp = c; cp->name != NULL; ++cp) { if (cp->flags & (C_IGNORE | C_PERM | C_TEMP)) continue; /* * Boolean flags are 0 or 1, but only set N in 100 where the * variable's min value is N. Set the flag if we rolled >= * the min, 0 otherwise. */ if (cp->flags & C_BOOL) *cp->v = MMRAND(1, 100) <= cp->min ? 1 : 0; else *cp->v = CONF_RAND(cp); } config_compression(); /* Clear operations values if the whole run is read-only. */ if (g.c_ops == 0) for (cp = c; cp->name != NULL; ++cp) if (cp->flags & C_OPS) *cp->v = 0; /* Multi-threaded runs cannot be replayed. */ if (g.replay && !SINGLETHREADED) die(0, "-r is incompatible with threaded runs"); /* * Periodically, set the delete percentage to 0 so salvage gets run, * as long as the delete percentage isn't nailed down. */ if (!g.replay && g.run_cnt % 10 == 0) { cp = config_find("delete_pct", strlen("delete_pct")); if (cp->name != NULL && !(cp->flags & (C_IGNORE | C_PERM | C_TEMP))) g.c_delete_pct = 0; } /* Reset the key count. */ g.key_cnt = 0; }
/* * config_setup -- * Initialize configuration for a run. */ void config_setup(void) { CONFIG *cp; /* Clear any temporary values. */ config_clear(); /* * Choose a data source type and a file type: they're interrelated (LSM * trees are only compatible with row-store) and other items depend on * them. */ if (!config_find_is_perm("data_source", strlen("data_source"))) switch (MMRAND(1, 3)) { case 1: config_single("data_source=file", 0); break; case 2: config_single("data_source=lsm", 0); break; case 3: config_single("data_source=table", 0); break; } if (!config_find_is_perm("file_type", strlen("file_type"))) switch (DATASOURCE("lsm") ? 3 : MMRAND(1, 3)) { case 1: config_single("file_type=fix", 0); break; case 2: config_single("file_type=var", 0); break; case 3: config_single("file_type=row", 0); break; } config_map_file_type(g.c_file_type, &g.type); /* * If data_source and file_type were both "permanent", we may still * have a mismatch. */ if (DATASOURCE("lsm") && g.type != ROW) { fprintf(stderr, "%s: lsm data_source is only compatible with row file_type\n", g.progname); exit(EXIT_FAILURE); } /* * Build the top-level object name: we're overloading data_source in * our configuration, LSM or KVS devices are "tables", but files are * tested as well. */ if ((g.uri = malloc(256)) == NULL) syserr("malloc"); strcpy(g.uri, DATASOURCE("file") ? "file:" : "table:"); if (DATASOURCE("helium")) strcat(g.uri, "dev1/"); strcat(g.uri, WT_NAME); /* Default single-threaded 10% of the time. */ cp = config_find("threads", strlen("threads")); if (!(cp->flags & C_PERM)) *cp->v = MMRAND(1, 100) < 10 ? 1: CONF_RAND(cp); /* Fill in random values for the rest of the run. */ for (cp = c; cp->name != NULL; ++cp) { if (cp->flags & (C_IGNORE | C_PERM | C_TEMP)) continue; /* * Boolean flags are 0 or 1, but only set N in 100 where the * variable's min value is N. Set the flag if we rolled >= * the min, 0 otherwise. */ if (cp->flags & C_BOOL) *cp->v = MMRAND(1, 100) <= cp->min ? 1 : 0; else *cp->v = CONF_RAND(cp); } /* Required shared libraries. */ if (DATASOURCE("helium") && access(HELIUM_PATH, R_OK) != 0) die(errno, "Levyx/helium shared library: %s", HELIUM_PATH); if (DATASOURCE("kvsbdb") && access(KVS_BDB_PATH, R_OK) != 0) die(errno, "kvsbdb shared library: %s", KVS_BDB_PATH); /* Some data-sources don't support user-specified collations. */ if (DATASOURCE("helium") || DATASOURCE("kvsbdb")) g.c_reverse = 0; config_checksum(); config_compression(); /* Clear operations values if the whole run is read-only. */ if (g.c_ops == 0) for (cp = c; cp->name != NULL; ++cp) if (cp->flags & C_OPS) *cp->v = 0; /* * Periodically, set the delete percentage to 0 so salvage gets run, * as long as the delete percentage isn't nailed down. */ if (!g.replay && g.run_cnt % 10 == 0) { cp = config_find("delete_pct", strlen("delete_pct")); if (cp->name != NULL && !(cp->flags & (C_IGNORE | C_PERM | C_TEMP))) g.c_delete_pct = 0; } /* * If this is an LSM run, set the cache size and crank up the insert * percentage. */ if (DATASOURCE("lsm")) { cp = config_find("cache", strlen("cache")); if (!(cp->flags & C_PERM)) g.c_cache = 30 * g.c_chunk_size; cp = config_find("insert_pct", strlen("insert_pct")); if (cp->name != NULL && !(cp->flags & (C_IGNORE | C_PERM | C_TEMP))) g.c_insert_pct = MMRAND(50, 85); } /* * Key/value minimum/maximum are related, correct unless specified by * the configuration. */ cp = config_find("key_min", strlen("key_min")); if (!(cp->flags & C_PERM) && g.c_key_min > g.c_key_max) g.c_key_min = g.c_key_max; cp = config_find("key_max", strlen("key_max")); if (!(cp->flags & C_PERM) && g.c_key_max < g.c_key_min) g.c_key_max = g.c_key_min; if (g.c_key_min > g.c_key_max) die(EINVAL, "key_min may not be larger than key_max"); cp = config_find("value_min", strlen("value_min")); if (!(cp->flags & C_PERM) && g.c_value_min > g.c_value_max) g.c_value_min = g.c_value_max; cp = config_find("value_max", strlen("value_max")); if (!(cp->flags & C_PERM) && g.c_value_max < g.c_value_min) g.c_value_max = g.c_value_min; if (g.c_value_min > g.c_value_max) die(EINVAL, "value_min may not be larger than value_max"); /* Reset the key count. */ g.key_cnt = 0; }
int loadEffect(cnode *root) { cnode *node; effect_uuid_t uuid; lib_entry_t *l; effect_descriptor_t *d; list_elem_t *e; node = config_find(root, LIBRARY_TAG); if (node == NULL) { return -EINVAL; } l = getLibrary(node->value); if (l == NULL) { ALOGW("loadEffect() could not get library %s", node->value); return -EINVAL; } node = config_find(root, UUID_TAG); if (node == NULL) { return -EINVAL; } if (stringToUuid(node->value, &uuid) != 0) { ALOGW("loadEffect() invalid uuid %s", node->value); return -EINVAL; } d = malloc(sizeof(effect_descriptor_t)); if (!d) { ALOGE("failed to allocate effect descriptor"); return -EINVAL; } if (l->desc->get_descriptor(&uuid, d) != 0) { char s[40]; uuidToString(&uuid, s, 40); ALOGW("Error querying effect %s on lib %s", s, l->name); free(d); return -EINVAL; } #if (LOG_NDEBUG==0) char s[256]; dumpEffectDescriptor(d, s, 256); ALOGV("loadEffect() read descriptor %p:%s",d, s); #endif if (EFFECT_API_VERSION_MAJOR(d->apiVersion) != EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) { ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name); free(d); return -EINVAL; } e = malloc(sizeof(list_elem_t)); if (!e) { return -ENOMEM; } e->object = d; e->next = l->effects; l->effects = e; // After the UUID node in the config_tree, if node->next is valid, // that would be sub effect node. // Find the sub effects and add them to the gSubEffectList node = node->next; int count = 2; bool hwSubefx = false, swSubefx = false; list_sub_elem_t *sube = NULL; if (node != NULL) { ALOGV("Adding the effect to gEffectSubList as there are sub effects"); sube = malloc(sizeof(list_sub_elem_t)); if (!sube) { ALOGE("failed to allocate sub element list"); return -ENOMEM; } sube->object = d; sube->sub_elem = NULL; sube->next = gSubEffectList; gSubEffectList = sube; } while (node != NULL && count) { if (addSubEffect(node)) { ALOGW("loadEffect() could not add subEffect %s", node->value); // Change the gSubEffectList to point to older list; gSubEffectList = sube->next; free(sube->sub_elem);// Free an already added sub effect sube->sub_elem = NULL; free(sube); return -ENOENT; } sub_effect_entry_t *subEntry = (sub_effect_entry_t*)gSubEffectList->sub_elem->object; effect_descriptor_t *subEffectDesc = (effect_descriptor_t*)(subEntry->object); // Since we return a dummy descriptor for the proxy during // get_descriptor call,we replace it with the correspoding // sw effect descriptor, but with Proxy UUID // check for Sw desc if (!((subEffectDesc->flags & EFFECT_FLAG_HW_ACC_MASK) == EFFECT_FLAG_HW_ACC_TUNNEL)) { swSubefx = true; *d = *subEffectDesc; d->uuid = uuid; ALOGV("loadEffect() Changed the Proxy desc"); } else hwSubefx = true; count--; node = node->next; } // 1 HW and 1 SW sub effect found. Set the offload flag in the Proxy desc if (hwSubefx && swSubefx) { d->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED; } return 0; }
int loadLibrary(cnode *root, const char *name) { cnode *node; void *hdl; audio_effect_library_t *desc; list_elem_t *e; lib_entry_t *l; node = config_find(root, PATH_TAG); if (node == NULL) { return -EINVAL; } hdl = dlopen(node->value, RTLD_NOW); if (hdl == NULL) { ALOGW("loadLibrary() failed to open %s", node->value); goto error; } desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR); if (desc == NULL) { ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR); goto error; } if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) { ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag); goto error; } if (EFFECT_API_VERSION_MAJOR(desc->version) != EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) { ALOGW("loadLibrary() bad lib version %08x", desc->version); goto error; } // add entry for library in gLibraryList l = malloc(sizeof(lib_entry_t)); l->name = strndup(name, PATH_MAX); l->path = strndup(node->value, PATH_MAX); l->handle = hdl; l->desc = desc; l->effects = NULL; pthread_mutex_init(&l->lock, NULL); e = malloc(sizeof(list_elem_t)); e->object = l; pthread_mutex_lock(&gLibLock); e->next = gLibraryList; gLibraryList = e; pthread_mutex_unlock(&gLibLock); ALOGV("getLibrary() linked library %p for path %s", l, node->value); return 0; error: if (hdl != NULL) { dlclose(hdl); } return -EINVAL; }