| /** |
| * 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); |
| } |
| } |
| |
| } |