/** Check the mood table. */
CHECK_MOODS = 2,
/** Check the playlist table. */
- CHECK_PLAYLISTS = 4
+ CHECK_PLAYLISTS = 4,
+ /** Check the attribute table against the audio file table. */
+ CHECK_ATTS = 8
};
int com_check(struct command_context *cc)
flags |= CHECK_AFT;
continue;
}
+ if (!strcmp(arg, "-A")) {
+ flags |= CHECK_ATTS;
+ continue;
+ }
if (!strcmp(arg, "-p")) {
flags |= CHECK_PLAYLISTS;
continue;
if (ret < 0)
return ret;
}
+ if (flags & CHECK_ATTS) {
+ ret = send_callback_request(attribute_check_callback, NULL,
+ afs_cb_result_handler, cc);
+ if (ret < 0)
+ return ret;
+ }
if (flags & CHECK_PLAYLISTS) {
ret = send_callback_request(playlist_check_callback,
NULL, afs_cb_result_handler, cc);
N: check
P: AFS_READ
D: Run integrity checks against osl tables.
-U: check [-a] [-m] [-p]
-H: Check the audio file table, the mood definitions and all
-H: defined playlists and report any inconsistencies found.
+U: check [-a] [-A] [-m] [-p]
+H: Check the audio file table, the attribute table, the mood definitions
+H: and all defined playlists. Report any inconsistencies.
H:
H: Options:
H:
H: whether the lyrics id and all entries in the audio file table are
H: valid.
H:
+H: -A Check the attribute table against the afs attribute bitmask of
+H: each audio file in the audio file table. Reports audio files
+H: whose attribute bitmask is invalid, i.e., has a bit set which
+H: does not correspond to any attribute of the attribute table.
+H:
H: -m Run syntax checks on all defined moods in the mood table.
H:
H: -p Check all playlists for lines that correspond to files not contained
H: in the audio file table.
H:
-H: If called without arguments, all three checks are run.
+H: If called without arguments, all checks are run.
---
N: rmatt
P: AFS_READ | AFS_WRITE
void get_attribute_bitmap(const uint64_t *atts, char *buf); /* needed by com_ls() */
int get_attribute_bitnum_by_name(const char *att_name, unsigned char *bitnum);
int get_attribute_text(uint64_t *atts, const char *delim, char **text);
+int attribute_check_callback(int fd, __a_unused const struct osl_object *query);
/* aft */
void aft_init(struct afs_table *t);
int aft_get_row_of_path(const char *path, struct osl_row **row);
+int aft_check_attributes(uint64_t att_mask, struct para_buffer *pb);
int open_and_update_audio_file(struct audio_file_data *afd);
int load_afd(int shmid, struct audio_file_data *afd);
int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi);
return ret;
}
+struct aft_check_atts_data {
+ uint64_t att_mask;
+ struct para_buffer *pb;
+};
+
+static int check_atts_of_audio_file(struct osl_row *row, void *data)
+{
+ struct aft_check_atts_data *acad = data;
+ int ret;
+ struct afs_info afsi;
+ char *path;
+ uint64_t bad_bits;
+
+ ret = get_afsi_of_row(row, &afsi);
+ if (ret < 0) {
+ para_printf(acad->pb, "cannot get afsi\n");
+ return ret;
+ }
+ bad_bits = afsi.attributes & ~acad->att_mask;
+ if (bad_bits == 0) /* OK */
+ return 0;
+ ret = get_audio_file_path_of_row(row, &path);
+ if (ret < 0) {
+ para_printf(acad->pb, "cannot get path\n");
+ return ret;
+ }
+ para_printf(acad->pb, "invalid attribute bits (%" PRIu64 "): %s\n",
+ bad_bits, path);
+ /* return success to keep looping */
+ return 1;
+}
+
+/**
+ * Iterate over all audio files and check the attribute bit mask.
+ *
+ * \param att_mask The mask of all valid attributes.
+ * \param pb Used for reporting inconsistencies.
+ *
+ * This reads the attribute bit mask of each audio file from the afs info
+ * structure stored in the audio file table and verifies that all set bits are
+ * also turned on in \a att_mask, i.e., correspond to an attribute of the
+ * attribute table. Audio files for which this is not the case are reported via
+ * \a pb.
+ *
+ * \return Standard. Inconsistencies are not regarded as errors.
+ *
+ * \sa \ref attribute_check_callback().
+ */
+int aft_check_attributes(uint64_t att_mask, struct para_buffer *pb)
+{
+ struct aft_check_atts_data acad = {.att_mask = att_mask, .pb = pb};
+
+ para_printf(pb, "checking attributes, mask: %" PRIx64 "\n", att_mask);
+ return audio_file_loop(&acad, check_atts_of_audio_file);
+}
+
/**
* Close the audio file table.
*
return ret;
}
+static int att_logical_or(struct osl_row *row, void *data)
+{
+ uint64_t *att_mask = data;
+ struct osl_object bitnum_obj;
+ int ret = osl_get_object(attribute_table, row, ATTCOL_BITNUM, &bitnum_obj);
+
+ if (ret < 0)
+ return ret;
+ *att_mask |= 1 << *(unsigned char *)bitnum_obj.data;
+ return 0;
+}
+
+/**
+ * Compute the attribute bit mask and check each afs info bitmap.
+ *
+ * \param fd Needed for the para buffer.
+ * \param query Unused.
+ *
+ * This iterates over all attributes in the attribute table and computes the
+ * logical or of 1 << b where b is the bit number of the attribute. The
+ * resulting bit mask is passed to aft_check_attributes() which performs the
+ * actual check.
+ *
+ * \return Standard.
+ *
+ * \sa \ref aft_check_attributes().
+ */
+int attribute_check_callback(int fd, __a_unused const struct osl_object *query)
+{
+ int ret;
+ uint64_t att_mask = 0; /* bits corresponding to a attributes */
+ struct para_buffer pb = {
+ .max_size = shm_get_shmmax(),
+ .private_data = &(struct afs_max_size_handler_data) {
+ .fd = fd,
+ .band = SBD_OUTPUT
+ },
+ .max_size_handler = afs_max_size_handler,
+ };
+
+ ret = osl_rbtree_loop(attribute_table, ATTCOL_BITNUM, &att_mask,
+ att_logical_or);
+ if (ret < 0) {
+ PARA_ERROR_LOG("attribute table loop failed: %s\n",
+ para_strerror(-ret));
+ return ret;
+ }
+ ret = aft_check_attributes(att_mask, &pb);
+ flush_and_free_pb(&pb);
+ return ret;
+}
+
/**
* Close the attribute table.
*