blob: ac9c3a8608490acad652087048435355c094df36 [file] [log] [blame]
/**
* 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 org.apache.distributedlog;
import com.google.common.annotations.VisibleForTesting;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
/**
* Log record with {@link DLSN} and <code>SequenceId</code>.
*
* <h3>Sequence Numbers</h3>
*
* <p>A log record will be assigned with an unique system generated sequence number {@link DLSN} when it is
* written to a log. At the mean time, a 64-bits long number is assigned to the record indicates its position
* within a log, which is called <code>SequenceId</code>. Besides {@link DLSN} and <code>SequenceID</code>,
* application can assign its own sequence number (called <code>TransactionID</code>) to the log record while
* writing it.
*
* <h4>Transaction ID</h4>
*
* <p>Transaction ID is a positive 64-bits long number that is assigned by the application. It is a very helpful
* field when application wants to organize the records and position the readers using their own sequencing method.
* A typical use case of <code>TransactionID</code> is DistributedLog Write Proxy. It assigns the non-decreasing
* timestamps to log records, which the timestamps could be used as `physical time` to implement `TTL` in a strong
* consistent database to achieve consistent `TTL` over replicas.
*
* <h4>DLSN</h4>
*
* <p>DistributedLog Sequence Number (<i>DLSN</i>) is the sequence number generated during written time.
* It is comparable and could be used to figure out the order between records. The DLSN is comprised with 3 components.
* They are <i>Log Segment Sequence Number</i>, <i>Entry Id</i> and <i>Slot Id</i>. (See {@link DLSN} for more details).
* The DLSN is usually used for comparison, positioning and truncation.
*
* <h4>Sequence ID</h4>
*
* <p>Sequence ID is introduced to address the drawback of <code>DLSN</code>, in favor of answering questions like
* `how many records written between two DLSNs`. It is a 64-bits monotonic increasing number (starting from zero).
* Sequence ids are only accessible by readers. That means writers don't know the sequence ids of records after they
* wrote them.
*/
public class LogRecordWithDLSN extends LogRecord {
private final DLSN dlsn;
private final long startSequenceIdOfCurrentSegment;
/**
* This empty constructor can only be called from Reader#readOp.
*/
LogRecordWithDLSN(DLSN dlsn, long startSequenceIdOfCurrentSegment) {
super();
this.dlsn = dlsn;
this.startSequenceIdOfCurrentSegment = startSequenceIdOfCurrentSegment;
}
@VisibleForTesting
public LogRecordWithDLSN(DLSN dlsn, long txid, byte[] data, long startSequenceIdOfCurrentSegment) {
super(txid, data);
this.dlsn = dlsn;
this.startSequenceIdOfCurrentSegment = startSequenceIdOfCurrentSegment;
}
@VisibleForTesting
public LogRecordWithDLSN(DLSN dlsn, long txid, ByteBuf buffer, long startSequenceIdOfCurrentSegment) {
// Need to make a copy since the passed payload is using a ref-count buffer that we don't know when could
// release, since the record is passed to the user. Also, the passed ByteBuf is coming from network and is
// backed by a direct buffer which we could not expose as a byte[]
super(txid, Unpooled.copiedBuffer(buffer));
this.dlsn = dlsn;
this.startSequenceIdOfCurrentSegment = startSequenceIdOfCurrentSegment;
}
long getStartSequenceIdOfCurrentSegment() {
return startSequenceIdOfCurrentSegment;
}
/**
* Get the sequence id of the record in the log.
*
* @return sequence id of the record in the log.
*/
public long getSequenceId() {
return startSequenceIdOfCurrentSegment + getPositionWithinLogSegment() - 1;
}
/**
* Get the DLSN of the record in the log.
*
* @return DLSN of the record in the log.
*/
public DLSN getDlsn() {
return dlsn;
}
@Override
public String toString() {
return "LogRecordWithDLSN{"
+ "dlsn=" + dlsn
+ ", txid=" + getTransactionId()
+ ", position=" + getPositionWithinLogSegment()
+ ", isControl=" + isControl()
+ ", isEndOfStream=" + isEndOfStream()
+ '}';
}
}