configuration. There is plenty more that could be done.
will lay out what you can and cannot change over a reconfigure. Any
other changes will require a full server restart.
-I intend to improve the situation, but for now this is how it is.
+The situation is gradually improving; this file tracks the current
+state.
* Options that might have to remain the same across restart
Arguably if there is anything in this section then that's a serious
bug!
-** alias
+** alias (enforced at reload only)
This defines how aliases are inserted into the track database. Need
to think about how changing it will affect things.
The search database will have to be rebuilt from scratch. This is
do-able but AFAIK we don't detect it.
-** user
+** user (enforced at reload only)
All the files will be owned by the wrong user!
this (refusing to accept modified configurations that purport to
change them) or explicitly ignore it.
-** home
+** home (enforced at reload)
-We absolutely cannot accept changing our state directory. If this is
-attempted it must be rejected.
+We absolutely cannot accept changing our state directory.
-** lock
+** lock (generates a deprecation warning)
Liable to be removed anyway.
-** nice_speaker
+** nice_speaker (generates a warning)
-Can't renice a running speaker to make it less nice (and we don't try
-to make it more nice). We ought to issue an error message and
-otherwise ignore.
+You can't renice a running speaker to make it less nice (and we don't
+try to make it more nice).
* Options that ought to be changable across reload but aren't
if(getenv("DISORDER_DEBUG"))
debugging = 1;
/* Read configuration */
- if(config_read(0/*!server*/))
+ if(config_read(0/*!server*/, NULL))
exit(EXIT_FAILURE);
/* Figure out our URL. This can still be overridden from the config file if
* necessary but it shouldn't be necessary in ordinary installations. */
static void cf_reconfigure(char attribute((unused)) **argv) {
/* Re-check configuration for server */
- if(config_read(1)) fatal(0, "cannot read configuration");
+ if(config_read(1, NULL)) fatal(0, "cannot read configuration");
if(disorder_reconfigure(getclient())) exit(EXIT_FAILURE);
}
default: fatal(0, "invalid option");
}
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
if(user) {
config->username = user;
config->password = 0;
default: fatal(0, "invalid option");
}
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
if(!maxbuffer)
maxbuffer = 2 * minbuffer;
argc -= optind;
/* create the event loop */
D(("create main loop"));
mainloop = g_main_loop_new(0, 0);
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
/* we'll need mixer support */
backend = uaudio_apis[0];
if(backend->open_mixer)
logname = pw->pw_name;
c->username = xstrdup(logname);
c->refresh = 15;
- c->prefsync = 3600;
+ c->prefsync = 0;
c->signal = SIGKILL;
c->alias = xstrdup("{/artist}{/album}{/title}{ext}");
c->lock = 1;
/** @brief (Re-)read the config file
* @param server If set, do extra checking
+ * @param oldconfig Old configuration for compatibility check
+ * @return 0 on success, non-0 on error
+ *
+ * If @p oldconfig is set, then certain compatibility checks are done between
+ * the old and new configurations.
*/
-int config_read(int server) {
+int config_read(int server,
+ const struct config *oldconfig) {
struct config *c;
char *privconf;
struct passwd *pw;
}
/* install default namepart and transform settings */
config_postdefaults(c, server);
+ if(oldconfig) {
+ int failed = 0;
+ if(strcmp(c->home, oldconfig->home)) {
+ error(0, "'home' cannot be changed without a restart");
+ failed = 1;
+ }
+ if(strcmp(c->alias, oldconfig->alias)) {
+ error(0, "'alias' cannot be changed without a restart");
+ failed = 1;
+ }
+ if(strcmp(c->user, oldconfig->user)) {
+ error(0, "'user' cannot be changed without a restart");
+ failed = 1;
+ }
+ if(c->nice_speaker != oldconfig->nice_speaker) {
+ error(0, "'nice_speaker' cannot be changed without a restart");
+ /* ...but we accept the new config anyway */
+ }
+ /* TODO namepart */
+ /* TODO stopword */
+ if(failed) {
+ error(0, "not installing incompatible new configuration");
+ return -1;
+ }
+ }
/* everything is good so we shall use the new config */
config_free(config);
/* warn about obsolete directives */
error(0, "'allow' will be removed in a future version");
if(c->trust.n)
error(0, "'trust' will be removed in a future version");
+ if(!c->lock)
+ error(0, "'lock' will be removed in a future version");
+ if(c->gap)
+ error(0, "'gap' will be removed in a future version");
+ if(c->prefsync)
+ error(0, "'prefsync' will be removed in a future version");
config = c;
return 0;
}
extern struct config *config;
/* the current configuration */
-int config_read(int server);
+int config_read(int server,
+ const struct config *oldconfig);
/* re-read config, return 0 on success or non-0 on error.
* Only updates @config@ if the new configuration is valid. */
openlog(progname, LOG_PID, LOG_DAEMON);
log_default = &log_syslog;
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
/* Find out current queue/recent list */
queue_read();
recent_read();
openlog(progname, LOG_PID, LOG_DAEMON);
log_default = &log_syslog;
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
/* Open the database */
trackdb_init(TRACKDB_NO_RECOVER);
trackdb_open(TRACKDB_OPEN_FOR_UPGRADE);
openlog(progname, LOG_PID, LOG_DAEMON);
log_default = &log_syslog;
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
info("started");
trackdb_init(TRACKDB_NO_RECOVER);
while(getppid() != 1) {
if(ev_child_setup(ev)) fatal(0, "ev_child_setup failed");
/* read config */
config_uaudio_apis = uaudio_apis;
- if(config_read(1))
+ if(config_read(1, NULL))
fatal(0, "cannot read configuration");
/* make sure the home directory exists and has suitable permissions */
make_home();
fatal(0, "specify only a dump file name");
path = argv[optind];
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
trackdb_init(recover|TRACKDB_MAY_CREATE);
trackdb_open(TRACKDB_NO_UPGRADE);
if(dump) {
default: fatal(0, "invalid option");
}
}
- if(config_read(1))
+ if(config_read(1, NULL))
fatal(0, "cannot read configuration");
if(logsyslog) {
openlog(progname, LOG_PID, LOG_DAEMON);
openlog(progname, LOG_PID, LOG_DAEMON);
log_default = &log_syslog;
}
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
xnice(config->nice_rescan);
sa.sa_handler = signal_handler;
sa.sa_flags = SA_RESTART;
break;
case SM_RELOAD:
D(("SM_RELOAD"));
- if(config_read(1))
+ if(config_read(1, NULL))
error(0, "cannot read configuration");
info("reloaded configuration");
break;
log_default = &log_syslog;
}
config_uaudio_apis = uaudio_apis;
- if(config_read(1)) fatal(0, "cannot read configuration");
+ if(config_read(1, NULL)) fatal(0, "cannot read configuration");
/* ignore SIGPIPE */
signal(SIGPIPE, SIG_IGN);
/* set nice value */
/* Close the track database */
trackdb_close();
/* (Re-)read the configuration */
- if(config_read(1/*server*/))
+ if(config_read(1/*server*/, config))
ret = -1;
else {
/* Tell the speaker it needs to reload its config too. */
openlog(progname, LOG_PID, LOG_DAEMON);
log_default = &log_syslog;
}
- if(config_read(0))
+ if(config_read(0, NULL))
fatal(0, "cannot read configuration");
trackdb_init(TRACKDB_NO_RECOVER);
trackdb_open(TRACKDB_NO_UPGRADE);
}
if(argc - optind < 3) fatal(0, "not enough arguments");
if(argc - optind > 3) fatal(0, "too many arguments");
- if(config_read(0)) fatal(0, "cannot read configuration");
+ if(config_read(0, NULL)) fatal(0, "cannot read configuration");
s = trackname_part(argv[optind], argv[optind+1], argv[optind+2]);
if(!s) fatal(0, "trackname_part returned NULL");
xprintf("%s\n", nullcheck(utf82mb(s)));