Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
*
* Licensed 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 com.vmware.xenon.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.EnumSet;
import com.vmware.xenon.common.Service.Action;
import com.vmware.xenon.common.ServiceDocumentDescription.DocumentIndexingOption;
import com.vmware.xenon.common.ServiceDocumentDescription.PropertyIndexingOption;
import com.vmware.xenon.common.ServiceDocumentDescription.PropertyUsageOption;
/**
* Base implementation class for Service documents. A service document is a PODO (data only object,
* no methods) that describes the service state. Even dynamic, state less services can have a
* document representing state-less computation results, or data gathered dynamically from other
* services
*/
public class ServiceDocument {
public enum DocumentRelationship {
IN_CONFLICT,
EQUAL,
NEWER_VERSION,
NEWER_UPDATE_TIME,
EQUAL_TIME,
EQUAL_VERSION, PREFERRED
}
/**
* Specifies {@link com.vmware.xenon.common.ServiceDocument} field usage option.
* This annotation is repeatable.
* Use {@link PropertyOptions} instead.
*
* @see PropertyUsageOption
*/
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(UsageOptions.class)
@Target(ElementType.FIELD)
public @interface UsageOption {
/**
* Field usage option to apply.
*/
PropertyUsageOption option();
}
/**
* This annotation defines field usage options.
* Use {@link PropertyOptions} instead.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UsageOptions {
/**
* Field usage options to apply.
*/
UsageOption[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface PropertyOptions {
/**
* Specifies how a field is used
* @return
*/
PropertyUsageOption[] usage() default {};
/**
* Specifies how a filed should be indexed.
* @return
*/
PropertyIndexingOption[] indexing() default {};
}
/**
* Limits about a {@link ServiceDocument}.
* In the rare case that the same ServiceDocument type is used to
* represent the state of different services and different limits are
* needed then {@link Service#getDocumentTemplate()} can still be used to
* override the values.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IndexingParameters {
/**
* Document indexing options.
* @return
*/
DocumentIndexingOption[] indexing() default {};
/**
* Max size of a serialized document
* @return
*/
int serializedStateSize() default ServiceDocumentDescription.DEFAULT_SERIALIZED_STATE_LIMIT;
/**
* Max versions to keep for a document.
* @return
*/
int versionRetention() default ServiceDocumentDescription.DEFAULT_VERSION_RETENTION_LIMIT;
/**
* Min versions to keep for a document.
*/
int versionRetentionFloor() default ServiceDocumentDescription.DEFAULT_VERSION_RETENTION_LIMIT / 2;
}
/**
* Annotations for ServiceDocumentDescription
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Documentation {
// sets property name
String name() default "";
// sets propertyDocumentation
String description() default "";
// sets exampleValue
String exampleString() default "";
}
public static final String FIELD_NAME_SELF_LINK = "documentSelfLink";
public static final String FIELD_NAME_VERSION = "documentVersion";
public static final String FIELD_NAME_EPOCH = "documentEpoch";
public static final String FIELD_NAME_KIND = "documentKind";
public static final String FIELD_NAME_UPDATE_TIME_MICROS = "documentUpdateTimeMicros";
public static final String FIELD_NAME_UPDATE_ACTION = "documentUpdateAction";
public static final String FIELD_NAME_DESCRIPTION = "documentDescription";
public static final String FIELD_NAME_OWNER = "documentOwner";
public static final String FIELD_NAME_SOURCE_LINK = "documentSourceLink";
public static final String FIELD_NAME_EXPIRATION_TIME_MICROS = "documentExpirationTimeMicros";
public static final String FIELD_NAME_AUTH_PRINCIPAL_LINK = "documentAuthPrincipalLink";
public static final String FIELD_NAME_TRANSACTION_ID = "documentTransactionId";
/**
* Field names ending with this suffix will be indexed as URI paths
*/
public static final String FIELD_NAME_SUFFIX_LINK = "Link";
public static final String FIELD_NAME_SUFFIX_LINKS = "Links";
/**
* Field names ending in Address will be indexed as StringFields.
*/
public static final String FIELD_NAME_SUFFIX_ADDRESS = "Address";
/**
* Optional description of the document, populated by the framework on requests to
* /template
*/
public ServiceDocumentDescription documentDescription;
/**
* Monotonically increasing number indicating the number of updates the local service instance
* has processed in the current host session or since creation, if the service is durable
*
* Infrastructure use only
*/
public long documentVersion;
/**
* Monotonically increasing number associated with a document owner. Each time ownership
* changes a protocol guarantees new owner will assign a higher epoch number and get consensus
* between peers before proceeding with replication.
*
* This field is not used for non replicated services
*
* Infrastructure use only
*/
public Long documentEpoch;
/**
* A structured string identifier for the document PODO type
*
* Infrastructure use only
*/
public String documentKind;
/**
* The relative URI path of the service managing this document
*/
public String documentSelfLink;
/**
* Document update time in microseconds since UNIX epoch
*
* Infrastructure use only
*/
public long documentUpdateTimeMicros;
/**
* Update action that produced the latest document version
*
* Infrastructure use only
*/
public String documentUpdateAction;
/**
* Expiration time in microseconds since UNIX epoch. If a document is found to be expired a
* running service instance will be deleted and the document will be marked deleted in the index
*/
public long documentExpirationTimeMicros;
/**
* Identity of the node that is assigned this document. Assignment is done through the node
* group partitioning service and it can change between versions
*
* Infrastructure use only
*/
public String documentOwner;
/**
* Link to the document that served as the source for this document. The source document is
* retrieved during a logical clone operation when this instance was created through a POST to a
* service factory
*/
public String documentSourceLink;
/**
* The relative URI path of the user principal who owns this document
*
* Infrastructure use only
*/
public String documentAuthPrincipalLink;
/**
* Refers to the transaction coordinator: if this particular state version is part of a
* pending transaction whose coordinator is `/core/transactions/[txid]`, it lets the system
* hide this version from queries, concurrent transactions and operations -- if they don't
* explicitly provide this id.
*/
public String documentTransactionId;
public void copyTo(ServiceDocument target) {
target.documentEpoch = this.documentEpoch;
target.documentDescription = this.documentDescription;
target.documentOwner = this.documentOwner;
target.documentSourceLink = this.documentSourceLink;
target.documentVersion = this.documentVersion;
target.documentKind = this.documentKind;
target.documentSelfLink = this.documentSelfLink;
target.documentUpdateTimeMicros = this.documentUpdateTimeMicros;
target.documentUpdateAction = this.documentUpdateAction;
target.documentExpirationTimeMicros = this.documentExpirationTimeMicros;
target.documentAuthPrincipalLink = this.documentAuthPrincipalLink;
target.documentTransactionId = this.documentTransactionId;
}
public static boolean isDeleted(ServiceDocument document) {
return document != null && Action.DELETE.toString().equals(document.documentUpdateAction);
}
/**
* Infrastructure use only.
* Compares two documents and returns an set describing the relationship between them.
*
* All relationship flags are relative to the first parameter (stateA). The timeEpsilon is used
* to determine if the update times between the two documents happened too close to each other
* to safely determine order.
*
* If document A is preferred, the PREFERRED option will be set
*/
public static EnumSet compare(ServiceDocument stateA,
ServiceDocument stateB,
ServiceDocumentDescription desc,
long timeEpsilon) {
boolean preferred = false;
EnumSet results = EnumSet.noneOf(DocumentRelationship.class);
long timeDifference;
if (stateB == null) {
results.add(DocumentRelationship.PREFERRED);
return results;
}
long epochA = stateA.documentEpoch != null ? stateA.documentEpoch : 0;
long epochB = stateB.documentEpoch != null ? stateB.documentEpoch : 0;
if (epochA > epochB ||
(epochA == epochB && stateA.documentVersion > stateB.documentVersion)) {
results.add(DocumentRelationship.NEWER_VERSION);
preferred = true;
} else if (epochA == epochB &&
stateA.documentVersion == stateB.documentVersion) {
results.add(DocumentRelationship.EQUAL_VERSION);
}
timeDifference = stateA.documentUpdateTimeMicros - stateB.documentUpdateTimeMicros;
if (timeDifference == 0) {
results.add(DocumentRelationship.EQUAL_TIME);
} else if (timeDifference > 0) {
results.add(DocumentRelationship.NEWER_UPDATE_TIME);
}
// TODO We only attempt conflict detection if versions match. Otherwise we pick the highest
// version which is not always correct. We need to formalize the eventual consistency model
// and do proper merges for divergent states (due to partitioning, etc). Dotted version
// vectors and other schemes are relatively easy to implement using our existing tracking
// data
if (results.contains(DocumentRelationship.EQUAL_VERSION)) {
if (Math.abs(timeDifference) < timeEpsilon) {
// documents changed within time epsilon so we can not safely determine which one
// is newer.
if (!ServiceDocument.equals(desc, stateA, stateB)) {
results.add(DocumentRelationship.IN_CONFLICT);
}
} else if (results.contains(DocumentRelationship.NEWER_UPDATE_TIME)) {
preferred = true;
}
}
if (preferred) {
results.add(DocumentRelationship.PREFERRED);
}
return results;
}
/**
* Compares ServiceDocument for equality. If they are same, then this method returns true;
* false otherwise.
*
* @param description ServiceDocumentDescription obtained by calling getDocumentTemplate
* ().documentDescription
* @param currentDocument current service document instance
* @param newDocument new service document instance
* @return true / false
*/
public static boolean equals(ServiceDocumentDescription description,
ServiceDocument currentDocument, ServiceDocument newDocument) {
if (currentDocument == null || newDocument == null) {
throw new IllegalArgumentException(
"Null Service documents cannot be checked for equality.");
}
try {
String currentSignature = Utils.computeSignature(currentDocument, description);
String newSignature = Utils.computeSignature(newDocument, description);
return currentSignature.equals(newSignature);
} catch (Exception e) {
if (e instanceof IllegalArgumentException) {
throw (IllegalArgumentException) e;
}
return false;
}
}
/**
* Returns whether or not the {@code name} is a built-in field or not.
*
* @param name Field name
* @return true/false
*/
public static boolean isBuiltInDocumentField(String name) {
switch (name) {
case ServiceDocument.FIELD_NAME_KIND:
case ServiceDocument.FIELD_NAME_EXPIRATION_TIME_MICROS:
case ServiceDocument.FIELD_NAME_OWNER:
case ServiceDocument.FIELD_NAME_SOURCE_LINK:
case ServiceDocument.FIELD_NAME_VERSION:
case ServiceDocument.FIELD_NAME_EPOCH:
case ServiceDocument.FIELD_NAME_UPDATE_TIME_MICROS:
case ServiceDocument.FIELD_NAME_UPDATE_ACTION:
case ServiceDocument.FIELD_NAME_SELF_LINK:
case ServiceDocument.FIELD_NAME_DESCRIPTION:
case ServiceDocument.FIELD_NAME_AUTH_PRINCIPAL_LINK:
case ServiceDocument.FIELD_NAME_TRANSACTION_ID:
return true;
default:
return false;
}
}
/**
* Returns whether or not the {@code name} should support auto merge by default or not
*
* @param name Field name
* @return true/false
*
* @see PropertyUsageOption#AUTO_MERGE_IF_NOT_NULL
* @see ServiceDocumentDescription
*/
public static boolean isAutoMergeEnabledByDefaultForField(String name) {
switch (name) {
case ServiceDocument.FIELD_NAME_EXPIRATION_TIME_MICROS:
return true;
default:
return false;
}
}
/**
* Returns whether or not the {@code name} is a built-in field that should be excluded from
* the service document signature computation.
*
* @see PropertyIndexingOption#EXCLUDE_FROM_SIGNATURE
*
* @param name Field name
* @return true/false
*/
public static boolean isBuiltInSignatureExcludedDocumentField(String name) {
switch (name) {
case ServiceDocument.FIELD_NAME_KIND:
case ServiceDocument.FIELD_NAME_OWNER:
case ServiceDocument.FIELD_NAME_SOURCE_LINK:
case ServiceDocument.FIELD_NAME_VERSION:
case ServiceDocument.FIELD_NAME_EPOCH:
case ServiceDocument.FIELD_NAME_UPDATE_TIME_MICROS:
case ServiceDocument.FIELD_NAME_SELF_LINK:
case ServiceDocument.FIELD_NAME_AUTH_PRINCIPAL_LINK:
case ServiceDocument.FIELD_NAME_TRANSACTION_ID:
return true;
default:
return false;
}
}
/**
* Returns whether or not the {@code name} is a built-in field that should be
* for infrastructure use only.
*
* @see PropertyUsageOption#INFRASTRUCTURE
*
* @param name Field name
* @return true/false
*/
public static boolean isBuiltInInfrastructureDocumentField(String name) {
switch (name) {
case ServiceDocument.FIELD_NAME_KIND:
case ServiceDocument.FIELD_NAME_EXPIRATION_TIME_MICROS:
case ServiceDocument.FIELD_NAME_OWNER:
case ServiceDocument.FIELD_NAME_SOURCE_LINK:
case ServiceDocument.FIELD_NAME_VERSION:
case ServiceDocument.FIELD_NAME_EPOCH:
case ServiceDocument.FIELD_NAME_UPDATE_TIME_MICROS:
case ServiceDocument.FIELD_NAME_SELF_LINK:
case ServiceDocument.FIELD_NAME_AUTH_PRINCIPAL_LINK:
case ServiceDocument.FIELD_NAME_TRANSACTION_ID:
return true;
default:
return false;
}
}
/**
* Returns whether or not the {@code name} is a built-in field that should not be indexed.
*
* @param name Field name
* @return true/false
*/
public static boolean isBuiltInNonIndexedDocumentField(String name) {
switch (name) {
case ServiceDocument.FIELD_NAME_DESCRIPTION:
case ServiceDocument.FIELD_NAME_UPDATE_ACTION:
return true;
default:
return false;
}
}
public static boolean isBuiltInDocumentFieldWithNullExampleValue(String name) {
switch (name) {
case ServiceDocument.FIELD_NAME_AUTH_PRINCIPAL_LINK:
case ServiceDocument.FIELD_NAME_SOURCE_LINK:
case ServiceDocument.FIELD_NAME_OWNER:
case ServiceDocument.FIELD_NAME_TRANSACTION_ID:
case ServiceDocument.FIELD_NAME_EPOCH:
return true;
default:
return false;
}
}
public static boolean isLink(String name) {
return name.endsWith(FIELD_NAME_SUFFIX_LINK);
}
public static boolean isLinks(String name) {
return name.endsWith(FIELD_NAME_SUFFIX_LINKS);
}
}