summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/hiscores.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-22 16:05:48 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-22 16:05:48 +0000
commitb9ea1d41f6595bebcf40ad36f5631de8d2c1f9df (patch)
tree04ef1c815e12fbfd2eba2e4090e2e1b297168331 /crawl-ref/source/hiscores.cc
parent28ca45a435ac680a813a619956785f1584b27401 (diff)
downloadcrawl-ref-b9ea1d41f6595bebcf40ad36f5631de8d2c1f9df.tar.gz
crawl-ref-b9ea1d41f6595bebcf40ad36f5631de8d2c1f9df.zip
Set dgl compiles to use a 1000 entry scoreboard.
Fixed a potential race condition when writing scores. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1911 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/hiscores.cc')
-rw-r--r--crawl-ref/source/hiscores.cc62
1 files changed, 38 insertions, 24 deletions
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 31784f4707..9ea744f3b2 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <memory>
#include "AppHdr.h"
#include "externs.h"
@@ -64,7 +65,7 @@
#endif
// enough memory allocated to snarf in the scorefile entries
-static scorefile_entry hs_list[SCORE_FILE_ENTRIES];
+static std::auto_ptr<scorefile_entry> hs_list[SCORE_FILE_ENTRIES];
// hackish: scorefile position of newest entry. Will be highlit during
// highscore printing (always -1 when run from command line).
@@ -98,20 +99,26 @@ void hiscores_new_entry( const scorefile_entry &ne )
int i, total_entries;
bool inserted = false;
- // open highscore file (reading) -- note that NULL is not fatal!
- scores = hs_open("r", score_file_name());
-
- for (i = 0; i < SCORE_FILE_ENTRIES; ++i)
- hs_list[i].reset();
+ // open highscore file (reading) -- NULL is fatal!
+ //
+ // Opening as a+ instead of r+ to force an exclusive lock (see
+ // hs_open) and to create the file if it's not there already.
+ scores = hs_open("a+", score_file_name());
+ if (scores == NULL)
+ end(1, true, "failed to open score file for writing");
+ // we're at the end of the file, seek back to beginning.
+ fseek(scores, 0, SEEK_SET);
+
// read highscore file, inserting new entry at appropriate point,
for (i = 0; i < SCORE_FILE_ENTRIES; i++)
{
- if (hs_read(scores, hs_list[i]) == false)
+ hs_list[i].reset(new scorefile_entry);
+ if (hs_read(scores, *hs_list[i]) == false)
break;
// compare points..
- if (ne.points >= hs_list[i].points && inserted == false)
+ if (!inserted && ne.points >= hs_list[i]->points)
{
newest_entry = i; // for later printing
inserted = true;
@@ -120,11 +127,11 @@ void hiscores_new_entry( const scorefile_entry &ne )
if (i+1 < SCORE_FILE_ENTRIES)
{
hs_list[i + 1] = hs_list[i];
- hs_list[i] = ne;
+ hs_list[i].reset(new scorefile_entry(ne));
i++;
} else {
// copy new entry to current position
- hs_list[i] = ne;
+ *hs_list[i] = ne;
}
}
}
@@ -135,31 +142,37 @@ void hiscores_new_entry( const scorefile_entry &ne )
newest_entry = i;
inserted = true;
// copy new entry
- hs_list[i] = ne;
+ hs_list[i].reset(new scorefile_entry(ne));
i++;
}
- total_entries = i;
-
- // close so we can re-open for writing
- hs_close(scores,"r", score_file_name());
-
- // open highscore file (writing) -- NULL *is* fatal here.
- scores = hs_open("w", score_file_name());
- if (scores == NULL)
+ // If we've still not inserted it, it's not a highscore.
+ if (!inserted)
{
- perror("Entry not added - failure opening score file for writing.");
+ hs_close(scores, "a+", score_file_name());
return;
}
+ total_entries = i;
+
+ // The old code closed and reopened the score file, leading to a
+ // race condition where one Crawl process could overwrite the
+ // other's highscore. Now we truncate and rewrite the file without
+ // closing it.
+ if (ftruncate(fileno(scores), 0))
+ end(1, true, "unable to truncate scorefile");
+
+ rewind(scores);
+
// write scorefile entries.
for (i = 0; i < total_entries; i++)
{
- hs_write(scores, hs_list[i]);
+ hs_write(scores, *hs_list[i]);
+ hs_list[i].reset(NULL);
}
// close scorefile.
- hs_close(scores, "w", score_file_name());
+ hs_close(scores, "a+", score_file_name());
}
void logfile_new_entry( const scorefile_entry &ne )
@@ -261,7 +274,8 @@ void hiscores_print_list( int display_count, int format )
// read highscore file
for (i = 0; i < SCORE_FILE_ENTRIES; i++)
{
- if (hs_read( scores, hs_list[i] ) == false)
+ hs_list[i].reset(new scorefile_entry);
+ if (hs_read( scores, *hs_list[i] ) == false)
break;
}
total_entries = i;
@@ -287,7 +301,7 @@ void hiscores_print_list( int display_count, int format )
if (i == newest_entry)
textcolor(YELLOW);
- hiscores_print_entry(hs_list[i], i, format, cprintf);
+ hiscores_print_entry(*hs_list[i], i, format, cprintf);
if (i == newest_entry)
textcolor(LIGHTGREY);