state_file: save only if something has changed

If nothing has changed since the last save, don't save the state
file.  Saving will spin up the hard drive, which is undesirable on
hosts where MPD is idling in background.
This commit is contained in:
Max Kellermann 2009-10-08 15:22:39 +02:00
parent 1e663b1869
commit ecb118f1ed
9 changed files with 87 additions and 0 deletions

1
NEWS
View File

@ -36,6 +36,7 @@ ver 0.16 (20??/??/??)
* renamed option "--stdout" to "--stderr"
* removed options --create-db and --no-create-db
* automatically update the database with Linux inotify
* state_file: save only if something has changed
* obey $(sysconfdir) for default mpd.conf location

View File

@ -31,6 +31,8 @@
#include "mixer_control.h"
#include "idle.h"
extern unsigned audio_output_state_version;
bool
audio_output_enable_index(unsigned idx)
{
@ -44,6 +46,8 @@ audio_output_enable_index(unsigned idx)
ao->enabled = true;
idle_add(IDLE_OUTPUT);
++audio_output_state_version;
return true;
}
@ -67,5 +71,7 @@ audio_output_disable_index(unsigned idx)
idle_add(IDLE_MIXER);
}
++audio_output_state_version;
return true;
}

View File

@ -34,6 +34,8 @@
#define AUDIO_DEVICE_STATE "audio_device_state:"
unsigned audio_output_state_version;
void
audio_output_state_save(FILE *fp)
{
@ -80,3 +82,9 @@ audio_output_state_read(const char *line)
ao->enabled = false;
return true;
}
unsigned
audio_output_state_get_version(void)
{
return audio_output_state_version;
}

View File

@ -34,4 +34,12 @@ audio_output_state_read(const char *line);
void
audio_output_state_save(FILE *fp);
/**
* Generates a version number for the current state of the audio
* outputs. This is used by timer_save_state_file() to determine
* whether the state has changed and the state file should be saved.
*/
unsigned
audio_output_state_get_version(void);
#endif

View File

@ -200,3 +200,21 @@ playlist_state_restore(const char *line, FILE *fp, struct playlist *playlist)
return true;
}
unsigned
playlist_state_get_hash(const struct playlist *playlist)
{
return playlist->queue.version ^
(getPlayerElapsedTime() << 8) ^
(playlist->current >= 0
? (queue_order_to_position(&playlist->queue,
playlist->current) << 16)
: 0) ^
((int)getPlayerCrossFade() << 20) ^
(getPlayerState() << 24) ^
(playlist->queue.random << 27) ^
(playlist->queue.repeat << 28) ^
(playlist->queue.single << 29) ^
(playlist->queue.consume << 30) ^
(playlist->queue.random << 31);
}

View File

@ -36,4 +36,13 @@ playlist_state_save(FILE *fp, const struct playlist *playlist);
bool
playlist_state_restore(const char *line, FILE *fp, struct playlist *playlist);
/**
* Generates a hash number for the current state of the playlist and
* the playback options. This is used by timer_save_state_file() to
* determine whether the state has changed and the state file should
* be saved.
*/
unsigned
playlist_state_get_hash(const struct playlist *playlist);
#endif

View File

@ -36,6 +36,13 @@ static char *state_file_path;
/** the GLib source id for the save timer */
static guint save_state_source_id;
/**
* These version numbers determine whether we need to save the state
* file. If nothing has changed, we won't let the hard drive spin up.
*/
static unsigned prev_volume_version, prev_output_version,
prev_playlist_version;
static void
state_file_write(void)
{
@ -57,6 +64,10 @@ state_file_write(void)
playlist_state_save(fp, &g_playlist);
while(fclose(fp) && errno == EINTR) /* nothing */;
prev_volume_version = sw_volume_state_get_hash();
prev_output_version = audio_output_state_get_version();
prev_playlist_version = playlist_state_get_hash(&g_playlist);
}
static void
@ -88,6 +99,10 @@ state_file_read(void)
}
while(fclose(fp) && errno == EINTR) /* nothing */;
prev_volume_version = sw_volume_state_get_hash();
prev_output_version = audio_output_state_get_version();
prev_playlist_version = playlist_state_get_hash(&g_playlist);
}
/**
@ -97,6 +112,13 @@ state_file_read(void)
static gboolean
timer_save_state_file(G_GNUC_UNUSED gpointer data)
{
if (prev_volume_version == sw_volume_state_get_hash() &&
prev_output_version == audio_output_state_get_version() &&
prev_playlist_version == playlist_state_get_hash(&g_playlist))
/* nothing has changed - don't save the state file,
don't spin up the hard disk */
return true;
state_file_write();
return true;
}

View File

@ -122,3 +122,9 @@ void save_sw_volume_state(FILE *fp)
{
fprintf(fp, SW_VOLUME_STATE "%u\n", volume_software_set);
}
unsigned
sw_volume_state_get_hash(void)
{
return volume_software_set;
}

View File

@ -36,4 +36,13 @@ read_sw_volume_state(const char *line);
void save_sw_volume_state(FILE *fp);
/**
* Generates a hash number for the current state of the software
* volume control. This is used by timer_save_state_file() to
* determine whether the state has changed and the state file should
* be saved.
*/
unsigned
sw_volume_state_get_hash(void);
#endif