/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package mesos.internal.log; // Represents a "promise" that a replica has made to a coordinator. A // promise is *implicitly* valid for _all_ future actions that get // performed on the replicated log (provided the action comes from the // same coordinator), until a new promise is made to a coordinator // with a higher id. Each replica writesevery promise it makes as a // log record so that it can recover this information after a failure. // TODO(benh): Does the promise actually need to be written to stable // storage? Can we get away with looking at the last written action // and using it's promised value? In this case, what happens if we // make a promise but don't receive an action from that coordinator? message Promise { required uint64 id = 1; } // Represents an "action" performed on the log. Each action has an // associated position in the log. In addition, each action (i.e., // position) will have been "promised" to a specific coordinator // (implicitly or explicitly) and may have been "performed" from a // specific coordinator. An action may also be "learned" to have // reached consensus. There are three types of possible actions that // can be performed on the log: nop (no action), append, and truncate. message Action { required uint64 position = 1; required uint64 promised = 2; optional uint64 performed = 3; optional bool learned = 4; enum Type { NOP = 1; APPEND = 2; TRUNCATE = 3; } message Nop {} message Append { required bytes bytes = 1; optional bytes cksum = 2; } message Truncate { required uint64 to = 1; // All positions before and exclusive of 'to'. } optional Type type = 5; // Set iff performed is set. optional Nop nop = 6; optional Append append = 7; optional Truncate truncate = 8; } // Represents a log record written to the local filesystem by a // replica. A log record may either be a promise or an action (defined // above). message Record { enum Type { PROMISE = 1; ACTION = 2; } required Type type = 1; optional Promise promise = 2; optional Action action = 3; } //////////////////////////////////////////////////// // Replicated log request/responses and messages. // //////////////////////////////////////////////////// // Represents a "promise" request from a coordinator with the // specified id to a replica. Most such requests will occur after a // coordinator has failed and a new coordinator is elected. In such a // case the position that the coordinator is asking the replica to // promise is implicitly *all* positions that the replica has made no // promises (thus the position field is not be used). In other // instances, however, a coordinator might be explicitly trying to // request that a replica promise a specific position in the log (such // as when trying to fill holes discovered during a client read), and // then position will be present. message PromiseRequest { required uint64 id = 1; optional uint64 position = 2; } // Represents a "promise" response from a replica back to a // coordinator with the specified id. A replica represents a 'nack' // (because it has promised a coordinator with a higher id) by setting // the okay field to false. The replica either sends back the highest // position it has recorded in the log (using the position field) or // the specific action (if any) it has at the position requested in // PromiseRequest. message PromiseResponse { required bool okay = 1; required uint64 id = 2; optional uint64 position = 4; optional Action action = 3; } // Represents a write request for a specific type of action. Note that // we deliberately do not include the entire Action as it contains // fields that are not relevant to a write request (e.g., promised, // performed) and rather than ignore them we exclude them for safety. message WriteRequest { required uint64 id = 1; required uint64 position = 2; optional bool learned = 3; required Action.Type type = 4; optional Action.Nop nop = 5; optional Action.Append append = 6; optional Action.Truncate truncate = 7; } // Represents a write response corresponding to a write request. If // okay is not true then the coordinator has been demoted. Both id and // position should always correspond to the id and position set in the // request. message WriteResponse { required bool okay = 1; required uint64 id = 2; required uint64 position = 3; } // Represents a learn (i.e., read) request and response. Note that a // non-learned position will not be returned. TODO(benh): Allow // learning more than one position at a time. message LearnRequest { required uint64 position = 1; } message LearnResponse { required bool okay = 1; optional Action action = 2; } // Represents a "learned" event, that is, when a particular action has // been agreed upon (reached consensus). message LearnedMessage { required Action action = 1; }