Refactor the commit aggregation algorightm for the leader

Previously the leader called Futures.successfulAsList() to wait for responses to an AppendEntries RPC call after an CommitOperation from a client. If a replica was down or otherwise missing, it might take a long time for the RPC to fail (perhaps because of a socket timeout). Therefore, even if the entry was successfully committed the leader still had to wait for the Future representing the down replica to fail. This could potentially take a long time and one missing/misbehaving replica could tank throughput. In the newly implemented approach, the leader keeps track of how many AppendEntry RPCs fail/succeed and trips the future as soon as one of those values crossed the majority line. It is no longer possible for an operation taking a long time on one replica to needlessly hold up an already committed entry.
Fixed bug that would throw NullPointerException when an Exception had a null message
Add last_log_index to AppendEntriesResponse
Prevent leader from expensive backwards probing. Fixes #7
When determining success or failure success can be equal to half but failure cannot
Fix bug where nextIndex can fall below zero
Increased default batch size for leader on quick catch-up path
Remove unneded storage of constructor parameter