blob: 91f29b22cfd8a0f5f44469f6ec00e08a3a2fa2e6 [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.ignite.internal.binary;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
/**
* Binary schema registry. Contains all well-known object schemas.
* <p>
* We rely on the fact that usually object has only few different schemas. For this reason we inline several
* of them with optional fallback to normal hash map lookup.
*
*/
public class BinarySchemaRegistry {
/** Empty schema ID. */
private static final int EMPTY = 0;
/** Whether registry still works in inline mode. */
private volatile boolean inline = true;
/** First schema ID. */
private int schemaId1;
/** Second schema ID. */
private int schemaId2;
/** Third schema ID. */
private int schemaId3;
/** Fourth schema ID. */
private int schemaId4;
/** First schema. */
private BinarySchema schema1;
/** Second schema. */
private BinarySchema schema2;
/** Third schema. */
private BinarySchema schema3;
/** Fourth schema. */
private BinarySchema schema4;
/** Schemas with COW semantics. */
private volatile HashMap<Integer, BinarySchema> schemas;
/**
* Get schema for the given ID. We rely on very relaxed memory semantics here assuming that it is not critical
* to return false-positive {@code null} values.
*
* @param schemaId Schema ID.
* @return Schema or {@code null}.
*/
@Nullable public BinarySchema schema(int schemaId) {
if (inline) {
if (schemaId == schemaId1)
return schema1;
else if (schemaId == schemaId2)
return schema2;
else if (schemaId == schemaId3)
return schema3;
else if (schemaId == schemaId4)
return schema4;
}
else {
HashMap<Integer, BinarySchema> schemas0 = schemas;
// Null can be observed here due to either data race or race condition when switching to non-inlined mode.
// Both of them are benign for us because they lead only to unnecessary schema re-calc.
if (schemas0 != null)
return schemas0.get(schemaId);
}
return null;
}
/**
* Add schema.
*
* @param schemaId Schema ID.
* @param schema Schema.
*/
public void addSchema(int schemaId, BinarySchema schema) {
synchronized (this) {
if (inline) {
// Check if this is already known schema.
if (schemaId == schemaId1 || schemaId == schemaId2 || schemaId == schemaId3 || schemaId == schemaId4)
return;
// Try positioning new schema in inline mode.
if (schemaId1 == EMPTY) {
schemaId1 = schemaId;
schema1 = schema;
inline = true; // Forcing HB edge just in case.
return;
}
if (schemaId2 == EMPTY) {
schemaId2 = schemaId;
schema2 = schema;
inline = true; // Forcing HB edge just in case.
return;
}
if (schemaId3 == EMPTY) {
schemaId3 = schemaId;
schema3 = schema;
inline = true; // Forcing HB edge just in case.
return;
}
if (schemaId4 == EMPTY) {
schemaId4 = schemaId;
schema4 = schema;
inline = true; // Forcing HB edge just in case.
return;
}
// No luck, switching to hash map mode.
HashMap<Integer, BinarySchema> newSchemas = new HashMap<>();
newSchemas.put(schemaId1, schema1);
newSchemas.put(schemaId2, schema2);
newSchemas.put(schemaId3, schema3);
newSchemas.put(schemaId4, schema4);
newSchemas.put(schemaId, schema);
schemas = newSchemas;
inline = false;
}
else {
HashMap<Integer, BinarySchema> newSchemas = new HashMap<>(schemas);
newSchemas.put(schemaId, schema);
schemas = newSchemas;
}
}
}
}