You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2014/02/19 19:56:10 UTC

[1/3] git commit: Revised the handling of truncation in leveldb to address the issue exposed by log catch-up.

Repository: mesos
Updated Branches:
  refs/heads/master 58804cad9 -> 83a39931e


Revised the handling of truncation in leveldb to address the issue exposed by log catch-up.


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/07537b58
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/07537b58
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/07537b58

Branch: refs/heads/master
Commit: 07537b580a3befb51b3d4533ce9ed01b84943a7f
Parents: 58804ca
Author: Jie Yu <yu...@gmail.com>
Authored: Tue Feb 18 16:29:56 2014 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Feb 19 10:28:15 2014 -0800

----------------------------------------------------------------------
 src/log/leveldb.cpp | 75 +++++++++++++++++++++++++++++-------------------
 src/log/leveldb.hpp |  6 +++-
 2 files changed, 51 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/07537b58/src/log/leveldb.cpp
----------------------------------------------------------------------
diff --git a/src/log/leveldb.cpp b/src/log/leveldb.cpp
index 7819963..386ebef 100644
--- a/src/log/leveldb.cpp
+++ b/src/log/leveldb.cpp
@@ -103,23 +103,27 @@ static string encode(uint64_t position, bool adjust = true)
 // Returns the position as represented in the specified slice
 // (performing a decrement as necessary to determine the actual
 // position represented).
-static uint64_t decode(const leveldb::Slice& s)
-{
-  // TODO(benh): Use varint decoding for VarInt64Comparator!
-  // uint64_t position;
-  // google::protobuf::io::ArrayInputStream _stream(s.data(), s.size());
-  // google::protobuf::io::CodedInputStream stream(&_stream);
-  // bool success = stream.ReadVarint64(&position);
-  // CHECK(success);
-  // return position - 1; // Actual position is less 1 of stringified.
-  Try<uint64_t> position = numify<uint64_t>(string(s.data(), s.size()));
-  CHECK_SOME(position);
-  return position.get() - 1; // Actual position is less 1 of stringified.
-}
+// TODO(jieyu): This function is not used (see RB-18252). However, we
+// still want to keep this function in case we need it in the future.
+// We comment it out to silence the warning (unused static function)
+// from the compiler.
+// static uint64_t decode(const leveldb::Slice& s)
+// {
+//   // TODO(benh): Use varint decoding for VarInt64Comparator!
+//   // uint64_t position;
+//   // google::protobuf::io::ArrayInputStream _stream(s.data(), s.size());
+//   // google::protobuf::io::CodedInputStream stream(&_stream);
+//   // bool success = stream.ReadVarint64(&position);
+//   // CHECK(success);
+//   // return position - 1; // Actual position is less 1 of stringified.
+//   Try<uint64_t> position = numify<uint64_t>(string(s.data(), s.size()));
+//   CHECK_SOME(position);
+//   return position.get() - 1; // Actual position is less 1 of stringified.
+// }
 
 
 LevelDBStorage::LevelDBStorage()
-  : db(NULL), first(0)
+  : db(NULL), first(None())
 {
   // Nothing to see here.
 }
@@ -241,6 +245,14 @@ Try<LevelDBStorage::State> LevelDBStorage::restore(const string& path)
           state.unlearned.insert(action.position());
         }
         state.end = std::max(state.end, action.position());
+
+        // Cache the first position in this replica so during a
+        // truncation, we can attempt to delete all positions from the
+        // first position up to the truncate position. Note that this
+        // is not the beginning position of the log, but rather the
+        // first position that remains (i.e., hasn't been deleted) in
+        // leveldb.
+        first = min(first, action.position());
         break;
       }
 
@@ -255,17 +267,6 @@ Try<LevelDBStorage::State> LevelDBStorage::restore(const string& path)
   LOG(INFO) << "Iterated through " << keys
             << " keys in the db in " << stopwatch.elapsed();
 
-  // Determine the first position still in leveldb so during a
-  // truncation we can attempt to delete all positions from the first
-  // position up to the truncate position. Note that this is not the
-  // beginning position of the log, but rather the first position that
-  // remains (i.e., hasn't been deleted) in leveldb.
-  iterator->Seek(encode(0));
-
-  if (iterator->Valid()) {
-    first = decode(iterator->key());
-  }
-
   delete iterator;
 
   return state;
@@ -327,6 +328,12 @@ Try<Nothing> LevelDBStorage::persist(const Action& action)
     return Error(status.ToString());
   }
 
+  // Updated the first position. Notice that we use 'min' here instead
+  // of checking 'isNone()' because it's likely that log entries are
+  // written out of order during catch-up (e.g. if a random bulk
+  // catch-up policy is used).
+  first = min(first, action.position());
+
   LOG(INFO) << "Persisting action (" << value.size()
             << " bytes) to leveldb took " << stopwatch.elapsed();
 
@@ -356,11 +363,19 @@ Try<Nothing> LevelDBStorage::persist(const Action& action)
 
     leveldb::WriteBatch batch;
 
+    CHECK_SOME(first);
+
     // Add positions up to (but excluding) the truncate position to
-    // the batch starting at the first position still in leveldb.
+    // the batch starting at the first position still in leveldb. It's
+    // likely that the first position is greater than the truncate
+    // position (e.g., during catch-up). In that case, we do nothing
+    // because there is nothing we can truncate.
+    // TODO(jieyu): We might miss a truncation if we do random (i.e.,
+    // out of order) bulk catch-up and the truncate operation is
+    // caught up first.
     uint64_t index = 0;
-    while ((first + index) < action.truncate().to()) {
-      batch.Delete(encode(first + index));
+    while ((first.get() + index) < action.truncate().to()) {
+      batch.Delete(encode(first.get() + index));
       index++;
     }
 
@@ -373,7 +388,9 @@ Try<Nothing> LevelDBStorage::persist(const Action& action)
         LOG(WARNING) << "Ignoring leveldb batch delete failure: "
                      << status.ToString();
       } else {
-        first = action.truncate().to(); // Save the new first position!
+        // Save the new first position!
+        CHECK_LT(first.get(), action.truncate().to());
+        first = action.truncate().to();
 
         LOG(INFO) << "Deleting ~" << index
                   << " keys from leveldb took " << stopwatch.elapsed();

http://git-wip-us.apache.org/repos/asf/mesos/blob/07537b58/src/log/leveldb.hpp
----------------------------------------------------------------------
diff --git a/src/log/leveldb.hpp b/src/log/leveldb.hpp
index 7eb51be..1df4173 100644
--- a/src/log/leveldb.hpp
+++ b/src/log/leveldb.hpp
@@ -21,6 +21,8 @@
 
 #include <leveldb/db.h>
 
+#include <stout/option.hpp>
+
 #include "log/storage.hpp"
 
 namespace mesos {
@@ -41,7 +43,9 @@ public:
 
 private:
   leveldb::DB* db;
-  uint64_t first; // First position still in leveldb, used during truncation.
+
+  // First position still in leveldb, used during truncation.
+  Option<uint64_t> first;
 };
 
 } // namespace log {


[2/3] git commit: Added log storage test for testing truncation.

Posted by ji...@apache.org.
Added log storage test for testing truncation.


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/91992032
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/91992032
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/91992032

Branch: refs/heads/master
Commit: 919920329f9441fb125eecbeecabd48245aa2851
Parents: 07537b5
Author: Jie Yu <yu...@gmail.com>
Authored: Tue Feb 18 22:23:40 2014 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Feb 19 10:45:37 2014 -0800

----------------------------------------------------------------------
 src/Makefile.am         |   5 +-
 src/log/leveldb.cpp     |   4 +-
 src/tests/log_tests.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 200 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/91992032/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 768c66a..e02d416 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,7 @@ MESOS_CPPFLAGS += -I../include
 MESOS_CPPFLAGS += -I../$(BOOST)
 MESOS_CPPFLAGS += -I../$(PROTOBUF)/src
 MESOS_CPPFLAGS += -I../$(GLOG)/src
+MESOS_CPPFLAGS += -I../$(LEVELDB)/include
 
 if WITH_INCLUDED_ZOOKEEPER
   MESOS_CPPFLAGS += -I../$(ZOOKEEPER)/include
@@ -333,7 +334,7 @@ liblog_la_SOURCES +=							\
   messages/log.hpp							\
   messages/log.proto
 nodist_liblog_la_SOURCES = $(LOG_PROTOS)
-liblog_la_CPPFLAGS = -I../$(LEVELDB)/include $(MESOS_CPPFLAGS)
+liblog_la_CPPFLAGS = $(MESOS_CPPFLAGS)
 
 libmesos_no_3rdparty_la_LIBADD += liblog.la
 
@@ -351,7 +352,7 @@ libstate_la_SOURCES +=							\
   messages/state.hpp							\
   messages/state.proto
 nodist_libstate_la_SOURCES = $(STATE_PROTOS)
-libstate_la_CPPFLAGS = -I../$(LEVELDB)/include $(MESOS_CPPFLAGS)
+libstate_la_CPPFLAGS = $(MESOS_CPPFLAGS)
 
 libmesos_no_3rdparty_la_LIBADD += libstate.la
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/91992032/src/log/leveldb.cpp
----------------------------------------------------------------------
diff --git a/src/log/leveldb.cpp b/src/log/leveldb.cpp
index 386ebef..4cc39d0 100644
--- a/src/log/leveldb.cpp
+++ b/src/log/leveldb.cpp
@@ -131,11 +131,11 @@ LevelDBStorage::LevelDBStorage()
 
 LevelDBStorage::~LevelDBStorage()
 {
-  delete db; // Might be null if open failed in LevelDBStorage::recover.
+  delete db; // Might be null if open failed in LevelDBStorage::restore.
 }
 
 
-Try<LevelDBStorage::State> LevelDBStorage::restore(const string& path)
+Try<Storage::State> LevelDBStorage::restore(const string& path)
 {
   leveldb::Options options;
   options.create_if_missing = true;

http://git-wip-us.apache.org/repos/asf/mesos/blob/91992032/src/tests/log_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/log_tests.cpp b/src/tests/log_tests.cpp
index 7e6dbde..2613e41 100644
--- a/src/tests/log_tests.cpp
+++ b/src/tests/log_tests.cpp
@@ -37,12 +37,15 @@
 #include <stout/option.hpp>
 #include <stout/os.hpp>
 #include <stout/path.hpp>
+#include <stout/stopwatch.hpp>
 #include <stout/try.hpp>
 
 #include "log/catchup.hpp"
 #include "log/coordinator.hpp"
+#include "log/leveldb.hpp"
 #include "log/log.hpp"
 #include "log/network.hpp"
+#include "log/storage.hpp"
 #include "log/recover.hpp"
 #include "log/replica.hpp"
 #include "log/tool/initialize.hpp"
@@ -119,6 +122,198 @@ TEST(NetworkTest, Watch)
 }
 
 
+template <typename T>
+class LogStorageTest : public TemporaryDirectoryTest {};
+
+
+typedef ::testing::Types<LevelDBStorage> LogStorageTypes;
+
+
+TYPED_TEST_CASE(LogStorageTest, LogStorageTypes);
+
+
+TYPED_TEST(LogStorageTest, Truncate)
+{
+  TypeParam storage;
+
+  Try<Storage::State> state = storage.restore(os::getcwd() + "/.log");
+  ASSERT_SOME(state);
+
+  EXPECT_EQ(Metadata::EMPTY, state.get().metadata.status());
+  EXPECT_EQ(0u, state.get().metadata.promised());
+  EXPECT_EQ(0u, state.get().begin);
+  EXPECT_EQ(0u, state.get().end);
+
+  // Append from position 0 to position 9.
+  for (uint64_t i = 0; i < 10; i++) {
+    Action action;
+    action.set_position(i);
+    action.set_promised(1);
+    action.set_performed(1);
+    action.set_learned(true);
+    action.set_type(Action::APPEND);
+    action.mutable_append()->set_bytes(stringify(i));
+
+    ASSERT_SOME(storage.persist(action));
+  }
+
+  for (uint64_t i = 0; i < 10; i++) {
+    Try<Action> action = storage.read(i);
+    ASSERT_SOME(action);
+
+    EXPECT_EQ(i, action.get().position());
+    EXPECT_EQ(1u, action.get().promised());
+    EXPECT_EQ(1u, action.get().performed());
+    EXPECT_TRUE(action.get().learned());
+    EXPECT_EQ(Action::APPEND, action.get().type());
+    ASSERT_TRUE(action.get().has_append());
+    EXPECT_EQ(stringify(i), action.get().append().bytes());
+  }
+
+  // Truncate to position 3 (at position 10).
+  Action truncate;
+  truncate.set_position(10);
+  truncate.set_promised(1);
+  truncate.set_performed(1);
+  truncate.set_learned(true);
+  truncate.set_type(Action::TRUNCATE);
+  truncate.mutable_truncate()->set_to(3);
+
+  ASSERT_SOME(storage.persist(truncate));
+
+  for (uint64_t i = 0; i < 11; i++) {
+    Try<Action> action = storage.read(i);
+
+    if (i < 3) {
+      // Position 0, 1 and 2 have been truncated.
+      EXPECT_ERROR(action);
+    } else if (i == 10) {
+      // Position 10 is a truncate.
+      EXPECT_EQ(i, action.get().position());
+      EXPECT_EQ(1u, action.get().promised());
+      EXPECT_EQ(1u, action.get().performed());
+      EXPECT_TRUE(action.get().learned());
+      EXPECT_EQ(Action::TRUNCATE, action.get().type());
+      ASSERT_TRUE(action.get().has_truncate());
+      EXPECT_EQ(3u, action.get().truncate().to());
+    } else {
+      EXPECT_EQ(i, action.get().position());
+      EXPECT_EQ(1u, action.get().promised());
+      EXPECT_EQ(1u, action.get().performed());
+      EXPECT_TRUE(action.get().learned());
+      EXPECT_EQ(Action::APPEND, action.get().type());
+      ASSERT_TRUE(action.get().has_append());
+      EXPECT_EQ(stringify(i), action.get().append().bytes());
+    }
+  }
+
+  // Truncate to position 10 (at position 11).
+  truncate.set_position(11);
+  truncate.set_promised(1);
+  truncate.set_performed(1);
+  truncate.set_learned(true);
+  truncate.set_type(Action::TRUNCATE);
+  truncate.mutable_truncate()->set_to(10);
+
+  ASSERT_SOME(storage.persist(truncate));
+
+  for (uint64_t i = 0; i < 12; i++) {
+    Try<Action> action = storage.read(i);
+
+    if (i < 10) {
+      // Position 0 to 9 have been truncated.
+      EXPECT_ERROR(action);
+    } else if (i == 10) {
+      // Position 10 is a truncate (to position 3).
+      EXPECT_EQ(i, action.get().position());
+      EXPECT_EQ(1u, action.get().promised());
+      EXPECT_EQ(1u, action.get().performed());
+      EXPECT_TRUE(action.get().learned());
+      EXPECT_EQ(Action::TRUNCATE, action.get().type());
+      ASSERT_TRUE(action.get().has_truncate());
+      EXPECT_EQ(3u, action.get().truncate().to());
+    } else if (i == 11) {
+      // Position 11 is a truncate (to position 10).
+      EXPECT_EQ(i, action.get().position());
+      EXPECT_EQ(1u, action.get().promised());
+      EXPECT_EQ(1u, action.get().performed());
+      EXPECT_TRUE(action.get().learned());
+      EXPECT_EQ(Action::TRUNCATE, action.get().type());
+      ASSERT_TRUE(action.get().has_truncate());
+      EXPECT_EQ(10u, action.get().truncate().to());
+    }
+  }
+}
+
+
+TYPED_TEST(LogStorageTest, TruncateWithEmptyLog)
+{
+  TypeParam storage;
+
+  Try<Storage::State> state = storage.restore(os::getcwd() + "/.log");
+  ASSERT_SOME(state);
+
+  Action truncate;
+  truncate.set_position(1);
+  truncate.set_promised(1);
+  truncate.set_performed(1);
+  truncate.set_learned(true);
+  truncate.set_type(Action::TRUNCATE);
+  truncate.mutable_truncate()->set_to(0);
+
+  ASSERT_SOME(storage.persist(truncate));
+
+  Try<Action> action0 = storage.read(0);
+  EXPECT_ERROR(action0);
+
+  Try<Action> action1 = storage.read(1);
+  EXPECT_EQ(1u, action1.get().position());
+  EXPECT_EQ(1u, action1.get().promised());
+  EXPECT_EQ(1u, action1.get().performed());
+  EXPECT_TRUE(action1.get().learned());
+  EXPECT_EQ(Action::TRUNCATE, action1.get().type());
+  ASSERT_TRUE(action1.get().has_truncate());
+  EXPECT_EQ(0u, action1.get().truncate().to());
+}
+
+
+TYPED_TEST(LogStorageTest, TruncateWithManyHoles)
+{
+  TypeParam storage;
+
+  Try<Storage::State> state = storage.restore(os::getcwd() + "/.log");
+  ASSERT_SOME(state);
+
+  Action truncate;
+  truncate.set_position(600020000);
+  truncate.set_promised(1);
+  truncate.set_performed(1);
+  truncate.set_learned(true);
+  truncate.set_type(Action::TRUNCATE);
+  truncate.mutable_truncate()->set_to(600000000);
+
+  // Measure the time taken for the truncation.
+  Stopwatch stopwatch;
+  stopwatch.start();
+
+  ASSERT_SOME(storage.persist(truncate));
+
+  // This truncation should not take much time because no position is
+  // actually being truncated.
+  EXPECT_GT(Seconds(1), stopwatch.elapsed());
+
+  Try<Action> action = storage.read(600020000);
+
+  EXPECT_EQ(600020000u, action.get().position());
+  EXPECT_EQ(1u, action.get().promised());
+  EXPECT_EQ(1u, action.get().performed());
+  EXPECT_TRUE(action.get().learned());
+  EXPECT_EQ(Action::TRUNCATE, action.get().type());
+  ASSERT_TRUE(action.get().has_truncate());
+  EXPECT_EQ(600000000u, action.get().truncate().to());
+}
+
+
 class ReplicaTest : public TemporaryDirectoryTest
 {
 protected:


[3/3] git commit: Updated the CHANGELOG for 0.18.0-rc2.

Posted by ji...@apache.org.
Updated the CHANGELOG for 0.18.0-rc2.


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/83a39931
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/83a39931
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/83a39931

Branch: refs/heads/master
Commit: 83a39931ee41133fae336604185a87e8e8b6b139
Parents: 9199203
Author: Jie Yu <yu...@gmail.com>
Authored: Wed Feb 19 10:54:13 2014 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Feb 19 10:54:20 2014 -0800

----------------------------------------------------------------------
 CHANGELOG | 78 ++++++++++++++++++++--------------------------------------
 1 file changed, 26 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/83a39931/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index 46636fd..5a9761a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,46 +2,32 @@ Release Notes - Mesos - Version 0.18.0
 --------------------------------------
 
 ** Bug
-    * [MESOS-422] - Master leader election should be more robust to
-    * stale ephemeral nodes
-    * [MESOS-537] -
-    * ZooKeeperMasterDetectorTest.MasterDetectorExpireSlaveZKSessionNewMaster
-    * is flaky
-    * [MESOS-672] - Web UI redirection does not work for hosts whose
-    * ip addresses are not publicly accessible
+    * [MESOS-422] - Master leader election should be more robust to stale ephemeral nodes
+    * [MESOS-537] - ZooKeeperMasterDetectorTest.MasterDetectorExpireSlaveZKSessionNewMaster is flaky
+    * [MESOS-672] - Web UI redirection does not work for hosts whose ip addresses are not publicly accessible
     * [MESOS-837] - AWAIT_READY should not depend on process::Clock
     * [MESOS-904] - Check for libcxx is missing in configure.ac
     * [MESOS-912] - Slave sometimes crashes with SIGPIPE
     * [MESOS-927] - OsTest.killtree is flaky
-    * [MESOS-937] - Fix "pure virtual method called" bug in
-    * zookeeper::ProcessWatcher
-    * [MESOS-952] - Clock::resume should adjust timeouts that were
-    * created in a paused/advanced Clock context.
-    * [MESOS-954] - The /__processes__ endpoint in libprocess is
-    * missing a needed lock acquisition.
-    * [MESOS-958] - Group should not ignore the ZNOAUTH error in
-    * creating the parent path for the group
+    * [MESOS-937] - Fix "pure virtual method called" bug in zookeeper::ProcessWatcher
+    * [MESOS-952] - Clock::resume should adjust timeouts that were created in a paused/advanced Clock context.
+    * [MESOS-954] - The /__processes__ endpoint in libprocess is missing a needed lock acquisition.
+    * [MESOS-958] - Group should not ignore the ZNOAUTH error in creating the parent path for the group
     * [MESOS-965] - GroupTest.GroupWatchWithSessionExpiration is flaky
-    * [MESOS-966] - symbolize.cc:235:58: error: invalid suffix on
-    * literal; C++11 requires a space between literal and identifier
+    * [MESOS-966] - symbolize.cc:235:58: error: invalid suffix on literal; C++11 requires a space between literal and identifier
     * [MESOS-977] - MasterZooKeeperTest.LostZooKeeperCluster is flaky
-    * [MESOS-985] -
-    * FaultToleranceTest.IgnoreKillTaskFromUnregisteredFramework is
-    * flaky
+    * [MESOS-985] - FaultToleranceTest.IgnoreKillTaskFromUnregisteredFramework is flaky
     * [MESOS-989] - Flaky whitelist tests
-    * [MESOS-991] - hashmap.hpp error: control reaches end of non-void
-    * function
-    * [MESOS-993] - Performance issue during replicated log catch-up
-    * when the initial log position is large
+    * [MESOS-991] - hashmap.hpp error: control reaches end of non-void function
+    * [MESOS-993] - Performance issue during replicated log catch-up when the initial log position is large
+		* [MESOS-1014] - Log truncation takes a long time during catch-up if the initial position is very large
 
 ** Documentation
     * [MESOS-926] - Document change to separate cgroup mounts
 
 ** Improvement
-    * [MESOS-903] - Store MasterInfo in ZK to enable master web UI
-    * redirection etc.
-    * [MESOS-943] - Provide an abstraction for asynchronous launching
-    * of subprocesses.
+    * [MESOS-903] - Store MasterInfo in ZK to enable master web UI redirection etc.
+    * [MESOS-943] - Provide an abstraction for asynchronous launching of subprocesses.
     * [MESOS-975] - Show git tag info in master and slave log output
 
 ** New Feature
@@ -59,26 +45,19 @@ Release Notes - Mesos - Version 0.17.0
     * [MESOS-902] - add post to libprocess
 
 ** Bug
-    * [MESOS-280] - ExecutorDriver methods' javadocs should not be
-    * refering to SchedulerDriver methods
-    * [MESOS-533] - SlaveRecoveryTest/0.CleanupExecutor is flaky on
-    * Jenkins.
+    * [MESOS-280] - ExecutorDriver methods' javadocs should not be refering to SchedulerDriver methods
+    * [MESOS-533] - SlaveRecoveryTest/0.CleanupExecutor is flaky on Jenkins.
     * [MESOS-789] - Make link to times in the webui clickable
     * [MESOS-799] - Mesos python egg is faulty on OS X Mavericks
     * [MESOS-831] - script-without-shebang
-    * [MESOS-861] - FaultToleranceTest.FrameworkReliableRegistration
-    * could hang
-    * [MESOS-875] - A recovering slave should not ignore valid status
-    * updates.
-    * [MESOS-877] - Future::then and Promise::associate have memory
-    * leaks.
+    * [MESOS-861] - FaultToleranceTest.FrameworkReliableRegistration could hang
+    * [MESOS-875] - A recovering slave should not ignore valid status updates.
+    * [MESOS-877] - Future::then and Promise::associate have memory leaks.
     * [MESOS-897] - Cleanup of stout headers from fedora review
     * [MESOS-913] - Help endpoint does not work on slaves.
-    * [MESOS-916] - add .gitignore-template file for ./bootstrap
-    * generated files
+    * [MESOS-916] - add .gitignore-template file for ./bootstrap generated files
     * [MESOS-925] - remove --without-curl from libprocess
-    * [MESOS-941] - Memory limit not correctly set when no memory
-    * resource set on executor level
+    * [MESOS-941] - Memory limit not correctly set when no memory resource set on executor level
     * [MESOS-951] - Build failure: in log/catchup.cpp on Clang
 
 ** Documentation
@@ -87,22 +66,17 @@ Release Notes - Mesos - Version 0.17.0
 ** Improvement
     * [MESOS-749] - Add support for multiple offers in launchTasks
     * [MESOS-772] - expose count of running tasks
-    * [MESOS-827] - Create LOOP_FOR(duration) macro to guard testing
-    * loop from running indefinitely
-    * [MESOS-860] - Get mesos' libprocess dependency glog to compile
-    * with clang and libc++
-    * [MESOS-863] - Get mesos' libprocess dependency protobuf to
-    * compile with clang and libc++
-    * [MESOS-864] - Eliminate the use of internal stdlibc++ templates
-    * for achieving libc++ compatiblity
+    * [MESOS-827] - Create LOOP_FOR(duration) macro to guard testing loop from running indefinitely
+    * [MESOS-860] - Get mesos' libprocess dependency glog to compile with clang and libc++
+    * [MESOS-863] - Get mesos' libprocess dependency protobuf to compile with clang and libc++
+    * [MESOS-864] - Eliminate the use of internal stdlibc++ templates for achieving libc++ compatiblity
     * [MESOS-896] - Enable newer versions of http_parser.
 
 ** New Feature
     * [MESOS-736] - Support catch-up replicated log
 
 ** Task
-    * [MESOS-323] - Get mesos compiling with clang to open up path
-    * forward to c++11
+    * [MESOS-323] - Get mesos compiling with clang to open up path forward to c++11
     * [MESOS-519] - Deprecate and remove old monitoring endpoint.