This assignment will have you implement a simple database. You are required to use block I/O to store player entries for the game that we have been making in class. The intention is to make the data persist while the program is not running. This is by far the most programming-intensive assignment, so you should get started immediately.
We have provided an interface by which you should design the database. This is to get you familiar with programming to interfaces as well as to provide consistent functionality for testing your solution.
Do not change the interface in any way! We will use this file exactly when compiling your code, not the sdbm.h file you supply.
The datebase will store player entries. The way information is laid out in a struct is fixed based on the following header file.
Do not change the struct in any way! We will also use this file exactly when compiling your code.
Your job is to implement the interface. How you do that, however, is up to you. You are required to store the players sequentially on the disk according to their playerID, but beyond that there are no requirements. You may use a single file or many. The file extension and its headers and footers are also left to you.
You may have noticed that keys are strings, not playerIDs. Each player's name is its key. This implies that you will have to come up with some sort of method to look up a playerID based on a name so that you can locate it in the database.
Accessing a file for every operation can be slow so you are also
required to load the database into memory using dynamic memory
operations. The space allocated in memory must be able to
increase and decrease as elements are added and removed from the
database. We recommend doubling the space each time it fills and
decreasing it by half each time it is reduced to a quarter. This
should prevent realloc from being called on
every sdbm_get and sdbm_remove. You are only
required to sync the cache with the disk when the database
calls on sdbm_open, sdbm_close,
and sdbm_sync.
The database should work with the game that we have been developing in class. When the game is started it requests the number of players and their names. Your database must be able to load the players from file. Note that only a subset of the players in the world will be in any given game. The database must be able to support thousands of players, but our game will never load that many at a time. You should not have to change the game implementation.
You must also supply code that tests your solution. We want to test both for coverage and for stability. Therefore, you must write unit tests for every function that you write. When grading your assignment we will use the tool gcov to ensure that you have 100% test coverage. 100% coverage will get you full credit.
You should also test the stability of your database. Inserting a single element and removing it might make you think that your solution is "perfect", but you might not notice bugs until you actually put the database through its paces. Randomly generate 10,000 players (names and stats), insert them into the database, and remove them all. We will be using gprof to verify the number of function calls.
Each of these tests should have its own executable, built by a rule
in the makefile. make coverage should build
the coverage executable and make
stability should build the stability
executable. The Makefile rules for coverage
and stability must compile them
with -fprofile-arcs -ftest-coverage and -pg,
respectively. Of course, make game should build
the game executable. Use the game.c file from
Tuesday's lecture in the blockio folder on bitbucket once we have
modified it in class to use sdbm.
| sdbm Functionality | 30 |
| sdbm Implementation (cache) | 20 |
| Test Coverage | 30 |
| Test Stability | 15 |
| Makefile | 5 |
Memory leaks/errors: -5 points, compiler warnings: -5 points
General assignment requirements, style and submission details:
gcc -std=c99 -pedantic -Wall -Wextra -O g++ -std=c++98 -pedantic -Wall -Wextra -ORemember: you will receive NO credit for programs that do not compile. Use incremental coding to insure that you always have a working program, even though it might be incomplete.