summaryrefslogtreecommitdiff
path: root/aft.c (follow)
Commit message (Collapse)AuthorAge
* aft: Dedoxification.Andre Noll2026-07-03
| | | | | Replace doxygen comments of structures and static functions in aft.c by ordinary C comments.
* Merge topic branch t/socket-cookie into masterAndre Noll2026-05-30
|\ | | | | | | | | | | | | | | | | | | | | | | AFS socket cookie replacement ----------------------------- A small but rather intrusive patch set which touches the guts of the afs callback mechanism. * t/socket-cookie: afs: Avoid the void * argument of send_lls_callback_request(). Kill afs socket cookie and afs_client_list. afs: Improve error handling of afs_signal_post_monitor().
| * Kill afs socket cookie and afs_client_list.Andre Noll2026-04-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We now create a per-command socket pair in the command handler and use the permanent server-afs socket to pass one end of the pair from the command handler to the afs process. With this approach only the command handlers can possibly talk to the afs process, so we don't need to worry about malicious or bogus connections arriving at the local socket. Consequently, we may remove the socket cookie and employ blocking I/O for the shared memory identifiers that are transferred through the per-command socket. Connections are now dispatched in one go, obviating the need to keep track of connected clients. So remove struct afs_client and the client list.
* | com_{touch,cpsi}: Don't clobber current status items.Andre Noll2026-05-20
|/ | | | | | | | Due to the missing condition, if the user runs touch or cpsi on an audio file which is not the current file, the audio file selector replaces the current status items by those of the file on which the touch/cpsi subcommand operated. Gimme that brown bag.
* Merge topic branch t/spdx into masterAndre Noll2026-03-26
|\ | | | | | | | | | | | | | | | | | | | | Switch to SPDX licence identifiers A single patch which replaces the first comment line of most .c and .h files containing the copyright notice by standardized SPDX (Software/System Package Data Exchange) nomenclature. * t/spdx: Switch to SPDX identifiers.
| * Switch to SPDX identifiers.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | Generated with sed -i 's|Copyright.*Andre Noll.*|SPDX-License-Identifier: GPL-2.0 */|g' *.c *.h followed by manually tweaking the result a bit. No license change intended.
* | Merge topic branch t/init into masterAndre Noll2026-03-25
|\ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Provide --init as a replacement for com_init() This change does not need a deprecation period because initialization is only necessary for new instances. * t/init: afs: Simplify table open functions. server: Replace the init subcommand by --init.
| * | afs: Simplify table open functions.Andre Noll2026-03-13
| |/ | | | | | | | | | | With the init subcommand gone, it's now a fatal error if at least one table cannot be opened. So remove the silly "table does not exist, but continue so that the user can create it" dance we currently do.
* | afs: Fix braino in afsi_change().Andre Noll2026-03-22
| | | | | | | | | | | | | | | | | | If the audio format info structure of an audio file changes, we have to generate an AFSI_CHANGE event no matter whether or not the file is the current file. For example, when the user runs touch --set-attribute to make a non-current file admissible, the file must be added to the score table so that it will eventually be streamed. Currently, we only generate the event if the afsi of the current audio file was modified. Fortunately, this is easy to fix.
* | Refuse to remove an attribute if it is still in use.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | This iterates over all audio files to check if the attribute to be removed is still set in the on-disk afs_info structure of the audio file. If at least one such audio file is detected, the rmatt subcommand aborts. With this new behaviour, the existing loop in aft_event_handler() which clears the corresponding bit from each on-disk afs_info can be removed. This was the only event handler that looked at the bit number passed, so we may as well pass NULL instead.
* | Improve selector loop.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently code outside of score.c needs to deal with two types of osl table rows: rows of the audio file table and rows of the score table. This foils type safety because the row pointers to different tables have the same type. We currently expose score rows to functions outside of score.c because the code in aft.c loops over the score table, and the osl loop callback receives a pointer to the current row as its first argument. This commit implements the static call_callback() in score.c, used as the osl callback, to avoid exposing the score row. The new function decodes the cells of the row to obtain the aft row and the score. These two values are then passed to the callback function passed to score_loop().
* | aft: Remove return value of sort_matching_paths().Andre Noll2026-03-17
| | | | | | | | | | This function never fails. The single condition under which it used to return negative is never true, so assert() that this is the case.
* | Remove pointless temporary variable from prepare_ls_row().Andre Noll2026-03-17
| |
* | Simplify and rename get_attribute_bitnum_by_name().Andre Noll2026-03-17
| | | | | | | | | | | | Return the bit number directly, avoiding the result pointer argument for the bit number. Remove the pointless "one" variable in one of the callers, the touch callback, while at it.
* | Move get_attribute_bitmap() to aft.c.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The public get_attribute_bitmap() is defined in attribute.c and called from the ls callback to print an attribute string such as xx--x, indicating which attribute bits are set/unset. This function should instead be part of aft.c where the ls subcommand is implemented, so move it there and make it static. The ls command needs to know the highest used attribute number to limit the output width of the attribute string. This number is currently maintained in a global variable of attribute.c. Provide the public attr_get_max_bitnum() helper to make it available to aft.c. It is easier to compute the value when it is needed than to maintain the value in a global variable. This is not performance critical anyway, since the ls command calls the function only once (rather than once per audio file listed).
* | Rename and improve get_attribute_text().Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | Rather than looking up each bit number in the attribute table, we now loop over all existing attributes and check whether the corresponding bit is on in the given attribute bitmask. This should be more efficient. Switch to para buffers and drop the delimiter argument since the only user, the callback of the ls subcommand, passes a constant value.
* | afs: Improve attribute checking code.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently both the audio file table and the attribute table implement a check function. The latter first computes the bitmask which corresponds to the defined attributes, then passes the resulting 64-bit integer to aft_check_attributes(), which loops over all rows. The loop callback de-serializes the afs_info structure of the row and checks the attributes of the row against the bitmask. This patch removes the check function of the attribute table as well as aft_check_attributes(). The replacement is the new public attr_get_defined_mask() in attribute.c. To make this work, the check function of the audio file table is modified to call the new function, then iterate over all rows as before, passing the mask to the existing loop callback. The loop callback is extended to perform the same check that aft_check_attributes() did before. This simplifies the code, and should perform better because we now de-serialize the afs_info struct only once per audio file rather than twice. As a result, the --attributes option of the check command has become unused. So we deprecate this option.
* | Pass callback arg and pbout to ->load().Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently the ->load() selector method takes a char ** argument, and both implementations allocate either an error message or an info string and return a pointer to it through this argument. There are four callers: Besides the ls and select callbacks, there is afs_init() to load the initial mood or playlist and afs_signal_post_monitor(), which reloads the current mood/playlist. The two command handlers pass any error messages to the client, the other two callers of ->load() call PARA_XXX_LOG to log errors. Only the select callback produces output on stdout, and only if select was run with --verbose. To improve in this error-prone approach we pass two arguments instead: a para_buffer pointer for stdout and the afs callback argument pointer for error messages. If the para_buffer pointer is NULL, no info string will be allocated. If the callback argument pointer is NULL, errors will be logged with PARA_ERROR_LOG().
* | com_ls(): Make ls --admissible=- work.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | We support "-" as the argument to the select subcommand as a shortcut for the name of the previously loaded mood or playlist. However, ls --admissible=- fails. This is inconsistent, so patch the ls subcommand to support this as well. Since the name of the previous mood or playlist is currently only known to afs.c, we have to declare previous_mop in afs.h and make it non-static in afs.c. Do the same with current_mop for consistency.
* | Implement selector abstraction.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently mood.c and playlist.c contain similar public functions. For example, there is mood_load() and playlist_load(), mood_loop() and playlist_loop(). Introduce struct selector_ops which contains methods such as ->load() and loop(). We define two instances of the new structure, one for the mood selector and one for the playlist selector. The structures can be constant, but need to be public. The methods can be static. The score table is now regarded as owned by the mood or playlist. It is no longer listed in afs_tables[] and afs_table_operations can go away. We don't need the global score_table variable anymore because all public functions of score.c now take a pointer to the table to operate on. Similarly, current_mood and current_playlist can be removed.
* | Simplify aft event handler.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Only the events generated by functions outside of aft.c need to be handled there. Self-generated events should be handled before the actual event is raised so that the corresponding event handler can ignore the event. This patch moves the code that deals with self-generated events out of the aft event handler to just before the afs_event() is called. The afsi change event is generated multiple times and the code is a bit longer, so we introduce afsi_change() for that. This removes a few lines more than it adds, and it gets us proper type checking by avoiding the void * argument of the event handler.
* | Remove struct afsi_change_event_data.Andre Noll2026-03-17
| | | | | | | | | | The event handlers only look at the aft row, so we may simply pass a pointer to the row instead of a pointer to struct afsi_change_event_data.
* | Remove struct rmatt_event_data.Andre Noll2026-03-17
| | | | | | | | | | It contains only an 8 bit integer, so we may as well just pass a pointer to uint8_t instead.
* | Remove the para_buffer argument of event handlers.Andre Noll2026-03-17
| | | | | | | | | | | | | | | | | | Only the event handler of the audio file table uses the para_buffer to send the "clearing bit" message on ATTRIBUTE_REMOVE events. It does so without NULL-checking the para_buffer pointer first, which is dubious but not a bug because the only source of ATTRIBUTE_REMOVE is the callback of the rmatt command, which passes non-NULL. We can simply omit the message, and remove the para_buffer argument from afs_event() and from all event handlers.
* | Simplify aft event handler.Andre Noll2026-03-17
| | | | | | | | | | | | We don't need to check the current aft row because make_status_items() does that for us. It also decodes the audio format handler information from the row, so there is no point in doing this twice.
* | aft_open(): Check the return value of osl_get_num_rows().Andre Noll2026-03-17
|/ | | | | | | This osl function fails only if the table pointer is NULL, which can never happen here because the table was opened successfully. Add an assertion to aft_open() which terminates the afs process if this impossible case actually happens.
* aft.c: Boolify send_afs_status().Andre Noll2026-03-01
| | | | | | The "parser_friendly" parameter is used as a boolean, so don't declare it as int. The function passes a reference to the bool via the callback method, so the callback, afs_stat_callback(), needs to be adjusted as well.
* Merge topic branch t/rm_setatt into masterAndre Noll2026-02-01
|\ | | | | | | | | | | | | | | | | | | Remove com_setatt() The setatt subcommand with its weird syntax was deprecated in 0.7.5 (2025-08) in favor of touch --set-attribute and touch --unset-attribute. Good riddance! * refs/heads/t/rm_setatt: Remove the setatt server subcommand.
| * Remove the setatt server subcommand.Andre Noll2026-01-28
| | | | | | | | | | The subcommand was deprecated in paraslash-0.7.5, when the touch subcommand grew equivalent functionality.
* | server: Remove deprecated listing modes of ls subcommand.Andre Noll2026-01-29
|/ | | | Both -l=c and -l=m are deprecated since paraslash-0.7.4, released on 2025-01-08.
* Revert "Speed up blob operations."Andre Noll2026-01-26
| | | | | | | | | This reverts commit da656fc87b1fe1de4f111223a46bbe007caa5941. Looks like we do need this: If, for example, an image is renamed, the status items need to reflect this, but the commit being reverted prevents that. Fixes: da656fc87b1fe1de4f111223a46bbe007caa5941
* afs: Remove v0.5.x on-disk afhi compatibility code.Andre Noll2025-09-30
| | | | | | | The condition in aft.c which is removed by this commit can no longer be true with the v0.7 database format. Hence afd->max_chunk_size always mirrors afd->afhi.max_chunk_size, so we can remove the former and adjust the single location in vss.c which still references it.
* Merge topic branch t/rm_sha1 into masterAndre Noll2025-09-22
|\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The series first drops the para_upgrade_db executable because it is no longer needed. This removes the penultimate user of the sha1 infrastructure. The remaining commits deal with the last user: the handshake between para_client and para_server. Since paraslash-0.7.0, client and server employ sha256 by default, but fall back to sha1 in order to stay compatible to old 0.6.x versions. After this series, server and client always employ sha256 as the hash algorithm, breaking compatibility with 0.6.x clients. As a result, the sha1 hash algorithm is no longer used anywhere, so the corresponding infrastructure is no longer needed. This gets rid of a fair amount of code. * refs/heads/t/rm_sha1: Rename hash2 -> hash. Remove sha1. Remove para_upgrade_db. aft: Compare the full hash, not just the first 20 bytes.
| * Rename hash2 -> hash.Andre Noll2025-05-22
| | | | | | | | | | Now that sha1 is no longer supported, the hash2 naming has become meaningless. Rename it back to "hash".
| * aft: Compare the full hash, not just the first 20 bytes.Andre Noll2025-05-22
| | | | | | | | | | | | | | | | | | | | | | | | | | In 0.7.0 the hash algorithm for the hash column of the audio file table changed from the 20 byte sha1 to the 32 byte sha256. However, the audio file selector kept calling hash_compare() as the comparator, which looks only at the first 20 bytes of the buffers passed. This omission is clearly a bug, but given that we still accept old clients which only know about sha1, it's benign because the truncated sha256 should not be worse than sha1. Fix the bug anyway. Fixes: 126b950f1bd70d1e5c200bc4157bbbb2798fc838
* | afh: Remove unnecessary fd argument of ->get_file_info().Andre Noll2025-08-28
| | | | | | | | | | All seven implementations of ->get_file_info() ignore the fd argument. The public compute_afhi() and the static get_file_info() don't need it either.
* | aft: Don't leak status_item_ls_data.path.Andre Noll2025-08-07
| | | | | | | | | | | | | | Currently we initialize this pointer variable by creating a copy of the memory mapped osl object on the heap, and leak this copy on exit. We may avoid the copy since we may as well look up the path again in make_status_items(). This is cheap because we already know the row of the audio file table at this point.
* | aft: Simplify make_inode_status_items().Andre Noll2025-08-07
| | | | | | | | | | | | | | | | | | This function calls get_audio_file_path_of_row() although the path is already known at this point. Moreover, since the function is called twice to produce the human-readable and the parser-friendly status items, we perform identical work in each call. We can easily avoid a system call by calling stat(2) only once in the caller, The mtime string is also computed twice, so move the computation into the caller as well.
* | Kill OSL_ERRNO_TO_PARA_ERROR.Andre Noll2025-07-13
| | | | | | | | | | The users outside of error.h may as well call osl(), which leaves only a single caller in error.h. Open-code the macro there and remove it.
* | aft: Reload afhi before creating the status items.Andre Noll2025-07-11
| | | | | | | | | | | | | | | | make_status_items() accesses the audio format handler information via status_item_ls_data.afhi, which was set when the current audio file was loaded. However, the pointers of the ahfi structure might have become stale if the server reloads the afs tables in between, for example when SIGHUP was received. This may lead to a crash or worse.
* | aft: Improve error path of open_and_update_audio_file().Andre Noll2025-07-11
| | | | | | | | | | | | | | | | | | | | | | On errors that occur after status_item_ls_data->path has been initialized, we return without setting ->path to NULL. This is bad because a subsequent event could call make_status_items(), which then proceeds using the invalid path. This commit adds a few labels to improve the error handling and to clean up properly in all cases. A side effect of this change is that on certain errors where we used to fail we now continue, trying the next best file as long as there are entries left in the score table.
* | aft.c: Shorten comment on memory-mapped files.Andre Noll2025-07-09
| | | | | | | | There is no reason to go into this much detail.
* | Improve error diagnostics of add server command.Andre Noll2025-07-06
| | | | | | | | | | | | | | If a file whose path does not match any known ending is attempted to be added, we silently ignore the file even if --verbose is given. This happens for example, if the audio format handler for the given file was not compiled in. Make this case more obvious by sending a message if --verbose is given.
* | aft: Avoid unnecessary allocation of current hash buffer.Andre Noll2025-06-29
| | | | | | | | | | | | | | Currently we allocate the hash pointer of the global status_item_ls_data structure once at first use. We can avoid the allocation by having it point to the global current_hash[]. This way it always contains an up-to-date value, so we no longer need to re-lookup the hash in aft_close().
* | Speed up blob operations.Andre Noll2025-06-29
| | | | | | | | | | The current status items are unaffected by any blob operations, so this code is completely unnecessary.
* | Merge topic branch t/deprecate_setatt into masterAndre Noll2025-06-29
|\ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | A single patch which deprecates the setatt server subcommand. This subcommand fails, for example, if the name of an audio file happens to end in '+' or '-'. The replacement for setatt is the touch subcommand, which gained two options to set or unset attributes. * refs/heads/t/deprecate_setatt: server: Deprecate setatt in favor of touch.
| * | server: Deprecate setatt in favor of touch.Andre Noll2025-05-19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds --set-attribute and --unset-attribute to the touch subcommand, re-implementing the features of the setatt command with a saner syntax. We augment the change_atts_data structure using pre-computed values for verbose and dry-run mode and pass a pointer to this structure rather than the general callback arg pointer. The existing setatt subcommand neither sets nor consults the two new booleans. The touch completer of para_client is updated to complete the two new options, executing the lsatt subcommand to get the attribute names. The manual and the test suite also need minor adjustments.
* | | Shrink struct rmatt_event_data.Andre Noll2025-05-28
| | | | | | | | | | | | | | | | | | | | | | | | The aft event handler needs to know the bit number of the attribute which is being removed in order to clear the bit in the afs info structure of each row of the audio file table. The handler does not need to know the attribute's name, though, and remove_attribute() already prints it, so remove this field from the event data structure.
* | | Introduce VSS_NEW_AUDIO_FILE to fix playlist updates.Andre Noll2025-05-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The playlist event handler handles afsi change events by moving the affected entry to the end of the playlist. This is the right thing to do if the event was triggered by virtual streaming system streaming a new file. It is incorrect, however, if the event was triggered by a subcommand such as touch. This commit introduces the new afs event type VSS_NEW_AUDIO_FILE to distinguish between the two different use cases. The audio file table event handler ignores the VSS_NEW_AUDIO_FILE event while the playlist event handler ignores the AFSI_CHANGE event. The moods event handler treats both events equally, Get rid of a pointless static one-liner function in playlist.c while at it.
* | | aft: Pass correct afsi argument to AFSI_CHANGE event handlers.Andre Noll2025-05-22
| |/ |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Each time a new audio file is opened for streaming, we update the numplayed and lastplayed fields of its afs info entry of the audio file table, then update the global afsi and ahfi structures, then trigger an AFSI_CHANGE event, which calls all table event handlers. The event handlers receive as arguments a pointer to the old afsi and a pointer to the already modified aft row. The AFSI_CHANGE event handler of the audio file table gets called in the situation described above, and also via the touch and cpsi subcommands, because these also change the afsi info structure and therefore trigger AFSI_CHANGE events as well. The handler checks whether the affected audio file is the current audio file, and if it is, extracts the modified afsi from the audio file table into the global afsi structure. The problem is that in case of the above "next audio file" scenario, the old afsi pointer points to the global afsi structure, which gets updated by the aft event handler. Therefore the event handlers which happen to run after the event handler of the audio file table see the already updated afsi through the old_afsi pointer. Since the audio file table happens to be the first table of the 7-element afs_tables[] array iterated by afs_event(), all six other event handlers see the incorrect afsi. However, only the moods event handler looks at the old afsi to update the mean and quadratic variation of the lastplayed and numplayed values of the afs statistics. Due to the bug described above, the old and new lastplayed and numplayed values coincide, and therefore the statistics update is a no-op. In practice, at least for moods with many admissible files, the values will only be slightly off, so the bug is rather benign. Fix this by renaming the on-stack new_afsi to old_afsi, adjusting initializations accordingly, and passing a pointer to this instance instead.