blob: f5937a7b60fc9db2224d4bf60d40fe320efaa07c [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.bookkeeper.meta;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
/**
* This class encapsulates ledger layout information that is persistently stored
* in registration service. It provides parsing and serialization methods of such
* information.
*/
@Slf4j
@Getter
@EqualsAndHashCode
@ToString
public class LedgerLayout {
// version of compatibility layout version
public static final int LAYOUT_MIN_COMPAT_VERSION = 1;
// version of ledger layout metadata
public static final int LAYOUT_FORMAT_VERSION = 2;
private static final String splitter = ":";
private static final String lSplitter = "\n";
// ledger manager factory class
private final String managerFactoryClass;
// ledger manager version
private final int managerVersion;
// layout version of how to store layout information
private final int layoutFormatVersion;
/**
* Ledger Layout Constructor.
*
* @param managerFactoryCls
* Ledger Manager Factory Class
* @param managerVersion
* Ledger Manager Version
*/
public LedgerLayout(String managerFactoryCls, int managerVersion) {
this(managerFactoryCls, managerVersion, LAYOUT_FORMAT_VERSION);
}
LedgerLayout(String managerFactoryCls, int managerVersion,
int layoutVersion) {
this.managerFactoryClass = managerFactoryCls;
this.managerVersion = managerVersion;
this.layoutFormatVersion = layoutVersion;
}
/**
* Generates a byte array based on the LedgerLayout object.
*
* @return byte[]
*/
public byte[] serialize() throws IOException {
String s =
new StringBuilder().append(layoutFormatVersion).append(lSplitter)
.append(managerFactoryClass).append(splitter).append(managerVersion).toString();
if (log.isDebugEnabled()) {
log.debug("Serialized layout info: {}", s);
}
return s.getBytes(StandardCharsets.UTF_8);
}
/**
* Parses a given byte array and transforms into a LedgerLayout object.
*
* @param bytes
* byte array to parse
* @return LedgerLayout
* @throws IOException
* if the given byte[] cannot be parsed
*/
public static LedgerLayout parseLayout(byte[] bytes) throws IOException {
String layout = new String(bytes, StandardCharsets.UTF_8);
if (log.isDebugEnabled()) {
log.debug("Parsing Layout: {}", layout);
}
String[] lines = layout.split(lSplitter);
try {
int layoutFormatVersion = Integer.parseInt(lines[0]);
if (LAYOUT_FORMAT_VERSION < layoutFormatVersion || LAYOUT_MIN_COMPAT_VERSION > layoutFormatVersion) {
throw new IOException("Metadata version not compatible. Expected "
+ LAYOUT_FORMAT_VERSION + ", but got " + layoutFormatVersion);
}
if (lines.length < 2) {
throw new IOException("Ledger manager and its version absent from layout: " + layout);
}
String[] parts = lines[1].split(splitter);
if (parts.length != 2) {
throw new IOException("Invalid Ledger Manager defined in layout : " + layout);
}
// ledger manager factory class
String managerFactoryCls = parts[0];
// ledger manager version
int managerVersion = Integer.parseInt(parts[1]);
return new LedgerLayout(managerFactoryCls, managerVersion, layoutFormatVersion);
} catch (NumberFormatException e) {
throw new IOException("Could not parse layout '" + layout + "'", e);
}
}
}