* \sa send_option_arg_callback_request(), send_standard_callback_request().
*/
int send_callback_request(callback_function *f, struct osl_object *query,
- struct osl_object *result)
+ callback_result_handler *result_handler,
+ void *private_result_data)
{
struct callback_query *cq;
- struct callback_result *cr;
- int ret, fd = -1, query_shmid, result_shmid;
+ int num_results = 0, ret, fd = -1, query_shmid, result_shmid;
void *query_shm, *result_shm;
char buf[sizeof(afs_socket_cookie) + sizeof(int)];
size_t query_shm_size = sizeof(*cq);
ret = send_bin_buffer(fd, buf, sizeof(buf));
if (ret < 0)
goto out;
- ret = recv_bin_buffer(fd, buf, sizeof(buf));
- if (ret < 0)
- goto out;
- if (ret != sizeof(int)) {
- ret = -E_AFS_SHORT_READ;
- goto out;
- }
- ret = *(int *) buf;
- if (ret <= 0)
- goto out;
- result_shmid = ret;
- ret = shm_attach(result_shmid, ATTACH_RO, &result_shm);
- if (ret >= 0) {
- assert(result);
- cr = result_shm;
- result->size = cr->result_size;
- result->data = para_malloc(result->size);
- memcpy(result->data, result_shm + sizeof(*cr), result->size);
- ret = shm_detach(result_shm);
+ for (;;) {
+ ret = recv_bin_buffer(fd, buf, sizeof(int));
+ if (ret <= 0)
+ goto out;
+ if (ret != sizeof(int)) {
+ ret = -E_AFS_SHORT_READ;
+ goto out;
+ }
+ ret = *(int *) buf;
+ if (ret <= 0)
+ goto out;
+ result_shmid = ret;
+ ret = shm_attach(result_shmid, ATTACH_RO, &result_shm);
+ if (ret >= 0) {
+ struct callback_result *cr = result_shm;
+ struct osl_object result;
+ num_results++;
+ result.size = cr->result_size;
+ result.data = result_shm + sizeof(*cr);
+ if (result.size) {
+ assert(result_handler);
+ ret = result_handler(&result, private_result_data);
+ if (shm_detach(result_shm) < 0)
+ PARA_ERROR_LOG("can not detach result\n");
+ }
+ } else
+ PARA_ERROR_LOG("attach result failed: %d\n", ret);
+ if (shm_destroy(result_shmid) < 0)
+ PARA_ERROR_LOG("destroy result failed\n");
if (ret < 0)
- PARA_ERROR_LOG("can not detach result\n");
- } else
- PARA_ERROR_LOG("attach result failed: %d\n", ret);
- if (shm_destroy(result_shmid) < 0)
- PARA_ERROR_LOG("destroy result failed\n");
- ret = 1;
+ break;
+ }
out:
if (shm_destroy(query_shmid) < 0)
PARA_ERROR_LOG("%s\n", "shm destroy error");
if (fd >= 0)
close(fd);
+ if (ret >= 0)
+ ret = num_results;
// PARA_DEBUG_LOG("callback_ret: %d\n", ret);
return ret;
}
*/
int send_option_arg_callback_request(struct osl_object *options,
int argc, char * const * const argv, callback_function *f,
- struct osl_object *result)
+ callback_result_handler *result_handler,
+ void *private_result_data)
{
char *p;
int i, ret;
strcpy(p, argv[i]); /* OK */
p += strlen(argv[i]) + 1;
}
- ret = send_callback_request(f, &query, result);
+ ret = send_callback_request(f, &query, result_handler,
+ private_result_data);
free(query.data);
return ret;
}
* send_option_arg_callback_request().
*/
int send_standard_callback_request(int argc, char * const * const argv,
- callback_function *f, struct osl_object *result)
+ callback_function *f, callback_result_handler *result_handler,
+ void *private_result_data)
{
- return send_option_arg_callback_request(NULL, argc, argv, f, result);
+ return send_option_arg_callback_request(NULL, argc, argv, f, result_handler,
+ private_result_data);
}
static int action_if_pattern_matches(struct osl_row *row, void *data)
* send_callback_request() otherwise.
*/
int stdin_command(int fd, struct osl_object *arg_obj, callback_function *f,
- unsigned max_len, struct osl_object *result)
+ unsigned max_len, callback_result_handler *result_handler,
+ void *private_result_data)
{
struct osl_object query, stdin_obj;
int ret;
memcpy(query.data, arg_obj->data, arg_obj->size);
memcpy((char *)query.data + arg_obj->size, stdin_obj.data, stdin_obj.size);
free(stdin_obj.data);
- ret = send_callback_request(f, &query, result);
+ ret = send_callback_request(f, &query, result_handler, private_result_data);
free(query.data);
return ret;
}
para_printf(&pb, "activated %s (%d admissible files)\n", current_mop?
current_mop : "dummy mood", num_admissible);
result->data = pb.buf;
- result->size = pb.size;
+ result->size = pb.offset;
return 1;
}
+int send_result(struct osl_object *result, void *private_result_data)
+{
+ int fd = *(int *)private_result_data;
+ if (!result->size)
+ return 1;
+ return send_bin_buffer(fd, result->data, result->size);
+}
+
int com_select(int fd, int argc, char * const * const argv)
{
- int ret;
- struct osl_object query, result;
+ struct osl_object query;
if (argc != 2)
return -E_AFS_SYNTAX;
query.data = argv[1];
query.size = strlen(argv[1]) + 1;
- ret = send_callback_request(com_select_callback, &query,
- &result);
- if (ret > 0 && result.data && result.size) {
- ret = send_va_buffer(fd, "%s", (char *)result.data);
- free(result.data);
- }
- return ret;
+ return send_callback_request(com_select_callback, &query,
+ &send_result, &fd);
}
static void init_admissible_files(char *arg)
return -E_BAD_TABLE_NAME;
}
}
- ret = send_callback_request(create_tables_callback, &query, NULL);
+ ret = send_callback_request(create_tables_callback, &query, NULL, NULL);
if (ret < 0)
return ret;
return send_va_buffer(fd, "successfully created afs table(s)\n");
{
unsigned flags = 0;
int i, ret;
- struct osl_object result;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!flags)
flags = ~0U;
if (flags & CHECK_AFT) {
- ret = send_callback_request(aft_check_callback, NULL, &result);
+ ret = send_callback_request(aft_check_callback, NULL, send_result, &fd);
if (ret < 0)
return ret;
- if (ret > 0) {
- ret = send_buffer(fd, (char *) result.data);
- free(result.data);
- if (ret < 0)
- return ret;
- }
}
if (flags & CHECK_PLAYLISTS) {
- ret = send_callback_request(playlist_check_callback, NULL, &result);
+ ret = send_callback_request(playlist_check_callback, NULL, send_result, &fd);
if (ret < 0)
return ret;
- if (ret > 0) {
- ret = send_buffer(fd, (char *) result.data);
- free(result.data);
- if (ret < 0)
- return ret;
- }
}
if (flags & CHECK_MOODS) {
- ret = send_callback_request(mood_check_callback, NULL, &result);
+ ret = send_callback_request(mood_check_callback, NULL, send_result, &fd);
if (ret < 0)
return ret;
- if (ret > 0) {
- ret = send_buffer(fd, (char *) result.data);
- free(result.data);
- if (ret < 0)
- return ret;
- }
}
return 1;
}
* \sa send_callback_request().
*/
typedef int callback_function(const struct osl_object *, struct osl_object *);
+typedef int callback_result_handler(struct osl_object *result, void *private);
+int send_result(struct osl_object *result, void *private_result_data);
+
__noreturn void afs_init(uint32_t cookie, int socket_fd);
void afs_event(enum afs_events event, struct para_buffer *pb,
void *data);
int send_callback_request(callback_function *f, struct osl_object *query,
- struct osl_object *result);
-int send_standard_callback_request(int argc, char * const * const argv,
- callback_function *f, struct osl_object *result);
+ callback_result_handler *result_handler,
+ void *private_result_data);
int send_option_arg_callback_request(struct osl_object *options,
- int argc, char * const * const argv, callback_function *f,
- struct osl_object *result);
+ int argc, char * const * const argv, callback_function *f,
+ callback_result_handler *result_handler,
+ void *private_result_data);
+int send_standard_callback_request(int argc, char * const * const argv,
+ callback_function *f, callback_result_handler *result_handler,
+ void *private_result_data);
int stdin_command(int fd, struct osl_object *arg_obj, callback_function *f,
- unsigned max_len, struct osl_object *result);
+ unsigned max_len, callback_result_handler *result_handler,
+ void *private_result_data);
int string_compare(const struct osl_object *obj1, const struct osl_object *obj2);
int for_each_matching_row(struct pattern_match_data *pmd);
ret = 1;
out:
ls_output->data = b.buf;
- ls_output->size = b.size;
+ ls_output->size = b.offset;
free(opts->data);
free(opts->data_ptr);
free(opts->patterns);
enum ls_sorting_method sort = LS_SORT_BY_PATH;
enum ls_listing_mode mode = LS_MODE_SHORT;
struct ls_options opts = {.patterns = NULL};
- struct osl_object query = {.data = &opts, .size = sizeof(opts)},
- ls_output;
+ struct osl_object query = {.data = &opts, .size = sizeof(opts)};
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
opts.mode = mode;
opts.num_patterns = argc - i;
ret = send_option_arg_callback_request(&query, opts.num_patterns,
- argv + i, com_ls_callback, &ls_output);
- if (ret > 0) {
- ret = send_buffer(fd, (char *)ls_output.data);
- free(ls_output.data);
- }
+ argv + i, com_ls_callback, send_result, &fd);
return ret;
}
if (!msg.buf)
return 0;
result->data = msg.buf;
- result->size = msg.size;
+ result->size = msg.offset;
return 1;
}
return 1;
}
-static int add_one_audio_file(const char *path, const void *private_data)
+int get_row_pointer_from_result(struct osl_object *result, void *private)
+{
+ struct osl_row **row = private;
+ *row = result->data;
+ return 1;
+}
+
+static int add_one_audio_file(const char *path, void *private_data)
{
int ret, send_ret = 1;
uint8_t format_num = -1;
- const struct private_add_data *pad = private_data;
+ struct private_add_data *pad = private_data;
struct afh_info afhi, *afhi_ptr = NULL;
struct osl_row *pb = NULL, *hs = NULL; /* path brother/hash sister */
- struct osl_object map, obj = {.data = NULL}, query, result = {.data = NULL};
+ struct osl_object map, obj = {.data = NULL}, query;
HASH_TYPE hash[HASH_SIZE];
ret = guess_audio_format(path);
goto out_free;
query.data = (char *)path;
query.size = strlen(path) + 1;
- ret = send_callback_request(path_brother_callback, &query, &result);
+ ret = send_callback_request(path_brother_callback, &query,
+ get_row_pointer_from_result, &pb);
if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
goto out_free;
- if (ret >= 0) {
- pb = *(struct osl_row **)result.data;
- free(result.data);
- }
ret = 1;
if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
if (pad->flags & ADD_FLAG_VERBOSE)
/* Check whether the database contains a file with the same hash. */
query.data = hash;
query.size = HASH_SIZE;
- ret = send_callback_request(hash_sister_callback, &query, &result);
+ ret = send_callback_request(hash_sister_callback, &query,
+ get_row_pointer_from_result, &hs);
if (ret < 0 && ret != -E_RB_KEY_NOT_FOUND)
goto out_unmap;
- if (ret >= 0) {
- hs = *(struct osl_row **)result.data;
- free(result.data);
- }
/* Return success if we already know this file. */
ret = 1;
if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
}
save_add_callback_buffer(hash, path, afhi_ptr, pad->flags, format_num, &obj);
/* Ask afs to consider this entry for adding. */
- ret = send_callback_request(com_add_callback, &obj, &result);
- if (ret > 0) {
- send_ret = send_va_buffer(pad->fd, "%s", (char *)result.data);
- free(result.data);
- }
+ ret = send_callback_request(com_add_callback, &obj, send_result, &pad->fd);
goto out_free;
out_unmap:
para_printf(&tad.pb, "no matches\n");
if (tad.pb.buf) {
result->data = tad.pb.buf;
- result->size = tad.pb.size;
+ result->size = tad.pb.offset;
return 1;
}
return ret < 0? ret : 0;
.lyrics_id = -1,
.image_id = -1
};
- struct osl_object query = {.data = &cto, .size = sizeof(cto)},
- result;
+ struct osl_object query = {.data = &cto, .size = sizeof(cto)};
int i, ret;
if (i >= argc)
return -E_AFT_SYNTAX;
ret = send_option_arg_callback_request(&query, argc - i,
- argv + i, com_touch_callback, &result);
- if (!ret)
- return 0;
- if (ret < 0) {
+ argv + i, com_touch_callback, send_result, &fd);
+ if (ret < 0)
send_va_buffer(fd, "%s\n", para_strerror(-ret));
- return ret;
- }
- ret = send_buffer(fd, (char *)result.data);
- free(result.data);
return ret;
}
}
static int com_rm_callback(const struct osl_object *query,
- __a_unused struct osl_object *result)
+ struct osl_object *result)
{
struct com_rm_action_data crd = {.flags = *(uint32_t *)query->data};
int ret;
}
if (crd.pb.buf) {
result->data = crd.pb.buf;
- result->size = crd.pb.size;
+ result->size = crd.pb.offset;
return 1;
}
return ret < 0? ret : 0;
int com_rm(int fd, int argc, char * const * const argv)
{
uint32_t flags = 0;
- struct osl_object query = {.data = &flags, .size = sizeof(flags)},
- result;
+ struct osl_object query = {.data = &flags, .size = sizeof(flags)};
int i, ret;
for (i = 1; i < argc; i++) {
if (i >= argc)
return -E_AFT_SYNTAX;
ret = send_option_arg_callback_request(&query, argc - i, argv + i,
- com_rm_callback, &result);
- if (!ret)
- return 0;
- if (ret < 0) {
+ com_rm_callback, send_result, &fd);
+ if (ret < 0)
send_va_buffer(fd, "%s\n", para_strerror(-ret));
- return ret;
- }
- ret = send_buffer(fd, (char *)result.data);
- free(result.data);
return ret;
}
}
if (cad.pb.buf) {
result->data = cad.pb.buf;
- result->size = cad.pb.size;
+ result->size = cad.pb.offset;
return 1;
}
return ret < 0? ret : 0;
{
unsigned flags = 0;
int i, ret;
- struct osl_object options = {.data = &flags, .size = sizeof(flags)},
- result;
+ struct osl_object options = {.data = &flags, .size = sizeof(flags)};
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
ret = send_option_arg_callback_request(&options, argc - i, argv + i,
- com_cpsi_callback, &result);
- if (!ret)
- return 0;
- if (ret < 0) {
+ com_cpsi_callback, send_result, &fd);
+ if (ret < 0)
send_va_buffer(fd, "%s\n", para_strerror(-ret));
- return ret;
- }
- ret = send_buffer(fd, (char *)result.data);
- free(result.data);
return ret;
}
para_printf(&pb, "checking audio file table...\n");
audio_file_loop(&pb, check_audio_file);
result->data = pb.buf;
- result->size = pb.size;
+ result->size = pb.offset;
return 1;
}
if (!laad.pb.buf)
return 0;
result->data = laad.pb.buf;
- result->size = laad.pb.size;
+ result->size = laad.pb.offset;
return 1;
}
int com_lsatt(int fd, int argc, char * const * const argv)
{
unsigned flags = 0;
- struct osl_object options = {.data = &flags, .size = sizeof(flags)},
- result;
+ struct osl_object options = {.data = &flags, .size = sizeof(flags)};
int ret, i;
for (i = 1; i < argc; i++) {
}
}
ret = send_option_arg_callback_request(&options, argc - i, argv + i,
- com_lsatt_callback, &result);
+ com_lsatt_callback, send_result, &fd);
if (!ret) {
if (argc > 1)
ret = send_va_buffer(fd, "no matches\n");
- return ret;
- }
- if (ret < 0) {
+ } else if (ret < 0)
send_va_buffer(fd, "%s\n", para_strerror(-ret));
- return ret;
- }
- ret = send_buffer(fd, (char *)result.data);
- free(result.data);
return ret;
}
if (argc < 3)
return -E_ATTR_SYNTAX;
return send_standard_callback_request(argc - 1, argv + 1, com_setatt_callback,
- NULL);
+ NULL, NULL);
}
struct addatt_event_data {
if (ret < 0)
para_printf(&pb, "%s: %s\n", p, para_strerror(-ret));
result->data = pb.buf;
- result->size = pb.size;
+ result->size = pb.offset;
return result->data? 0 : 1;
}
int com_addatt(int fd, int argc, char * const * const argv)
{
- struct osl_object result;
int ret;
if (argc < 2)
return -E_ATTR_SYNTAX;
ret = send_standard_callback_request(argc - 1, argv + 1, com_addatt_callback,
- &result);
- if (!ret)
- return 1;
+ send_result, &fd);
if (ret < 0)
- return ret;
- if (!result.data || !result.size)
- return 1;
- ret = send_va_buffer(fd, "%s", (char *) result.data);
- free(result.data);
+ send_va_buffer(fd, "%s\n", para_strerror(-ret));
return ret;
}
if (!pb.buf)
return 0;
result->data = pb.buf;
- result->size = pb.size;
+ result->size = pb.offset;
return 1;
}
int com_mvatt(int fd, int argc, char * const * const argv)
{
- struct osl_object result;
int ret;
if (argc != 3)
return -E_ATTR_SYNTAX;
ret = send_standard_callback_request(argc - 1, argv + 1, com_mvatt_callback,
- &result);
- if (!ret)
- return 1;
+ send_result, &fd);
if (ret < 0)
- return ret;
- if (!result.data || !result.size)
- return 1;
- ret = send_va_buffer(fd, "%s", (char *) result.data);
- free(result.data);
+ send_va_buffer(fd, "%s\n", para_strerror(-ret));
return ret;
}
if (!raad.num_removed)
para_printf(&raad.pb, "no match -- nothing removed\n");
result->data = raad.pb.buf;
- result->size = raad.pb.size;
+ result->size = raad.pb.offset;
return 1;
}
int com_rmatt(int fd, int argc, char * const * const argv)
{
int ret;
- struct osl_object result;
if (argc < 2)
return -E_ATTR_SYNTAX;
ret = send_standard_callback_request(argc - 1, argv + 1, com_rmatt_callback,
- &result);
- if (!ret)
- return 0;
- if (ret < 0) {
+ send_result, &fd);
+ if (ret < 0)
send_va_buffer(fd, "%s\n", para_strerror(-ret));
- return ret;
- }
- ret = send_buffer(fd, (char *)result.data);
- free(result.data);
return ret;
}
if (!lbad.pb.buf)
return 0;
result->data = lbad.pb.buf;
- result->size = lbad.pb.size;
+ result->size = lbad.pb.offset;
return 1;
}
static int com_lsblob(callback_function *f, int fd, int argc, char * const * const argv)
{
uint32_t flags = 0;
- struct osl_object options = {.data = &flags, .size = sizeof(flags)},
- result;
- int i, ret;
+ struct osl_object options = {.data = &flags, .size = sizeof(flags)};
+ int i;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
}
// if (argc > i)
// return -E_BLOB_SYNTAX;
- ret = send_option_arg_callback_request(&options, argc - i,
- argv + i, f, &result);
- if (!ret)
- return 0;
- if (ret < 0) {
- send_va_buffer(fd, "%s\n", para_strerror(-ret));
- return ret;
- }
- ret = send_buffer(fd, (char *)result.data);
- free(result.data);
- return ret;
+ return send_option_arg_callback_request(&options, argc - i,
+ argv + i, f, send_result, &fd);
}
static int cat_blob(struct osl_table *table, struct osl_row *row,
static int com_catblob(callback_function *f, int fd, int argc,
char * const * const argv)
{
- struct osl_object result;
- int ret;
-
if (argc < 2)
return -E_BLOB_SYNTAX;
- ret = send_standard_callback_request(argc - 1, argv + 1, f, &result);
- if (ret > 0) {
- ret = send_bin_buffer(fd, (char *)result.data, result.size);
- free(result.data);
- }
- return ret;
+ return send_standard_callback_request(argc - 1, argv + 1, f, send_result, &fd);
}
/** Used for removing rows from a blob table. */
afs_event(BLOB_RENAME, NULL, table);
}
result->data = rmbd.pb.buf;
- result->size = rmbd.pb.size;
+ result->size = rmbd.pb.offset;
return 1;
}
static int com_rmblob(callback_function *f, int fd, int argc,
char * const * const argv)
{
- int ret;
- struct osl_object result;
-
if (argc < 2)
return -E_MOOD_SYNTAX;
- ret = send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
- &result);
- if (ret > 0) {
- send_buffer(fd, (char *)result.data);
- free(result.data);
- }
- return ret;
+ return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
+ send_result, &fd);
}
static int com_addblob_callback(struct osl_table *table,
PARA_NOTICE_LOG("argv[1]: %s\n", argv[1]);
arg_obj.size = strlen(argv[1]) + 1;
arg_obj.data = (char *)argv[1];
- return stdin_command(fd, &arg_obj, f, 10 * 1024 * 1024, NULL);
+ return stdin_command(fd, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL);
}
static int com_mvblob_callback(struct osl_table *table,
if (argc != 3)
return -E_MOOD_SYNTAX;
return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
- NULL);
+ NULL, NULL);
}
#define DEFINE_BLOB_COMMAND(cmd_name, table_name, cmd_prefix) \
static unsigned files_pruned;
-int prune_disk_storage_file(const char *path, const void *private_data)
+int prune_disk_storage_file(const char *path, void *private_data)
{
HASH_TYPE hash[HASH_SIZE];
unsigned flags = *(unsigned *)private_data;
PARA_INFO_LOG("looking for unreferenced disk storage files\n");
FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) {
char *dirname = column_filename(t, i);
- ret = for_each_file_in_dir(dirname, prune_disk_storage_file, &t->desc->flags);
+ ret = for_each_file_in_dir(dirname, prune_disk_storage_file,
+ (unsigned *)&t->desc->flags);
free(dirname);
}
if (files_pruned)
osl_rbtree_loop(moods_table, BLOBCOL_ID, &pb,
check_mood);
result->data = pb.buf;
- result->size = pb.size;
+ result->size = pb.offset;
return 1;
}
* \return Standard.
*/
int for_each_file_in_dir(const char *dirname,
- int (*func)(const char *, const void *), const void *private_data)
+ int (*func)(const char *, void *), void *private_data)
{
DIR *dir;
struct dirent *entry;
unsigned col_num, unsigned *rank);
int for_each_file_in_dir(const char *dirname,
- int (*func)(const char *, const void *), const void *private_data);
+ int (*func)(const char *, void *), void *private_data);
ssize_t para_write_all(int fd, const void *buf, size_t size);
int para_lseek(int fd, off_t *offset, int whence);
int para_write_file(const char *filename, const void *buf, size_t size);
osl_rbtree_loop(playlists_table, BLOBCOL_ID, &pb,
check_playlist);
result->data = pb.buf;
- result->size = pb.size;
+ result->size = pb.offset;
return 1;
}