Improved BnP logging.
[voldemort.git] / src / java / voldemort / store / StoreDefinition.java
blob77e8cb614b99ad02e92deec4a90613de5c30251c
1 /*
2 * Copyright 2008-2009 LinkedIn, Inc
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
17 package voldemort.store;
19 import java.io.Serializable;
20 import java.util.HashMap;
21 import java.util.List;
23 import voldemort.client.RoutingTier;
24 import voldemort.serialization.SerializerDefinition;
25 import voldemort.store.slop.strategy.HintedHandoffStrategyType;
26 import voldemort.store.system.SystemStoreConstants;
27 import voldemort.utils.Utils;
29 import com.google.common.base.Objects;
31 /**
32 * The configuration information for a store.
36 public class StoreDefinition implements Serializable {
38 private static final long serialVersionUID = 1;
40 private final String name;
41 private final String type;
42 private final String description;
43 private final SerializerDefinition keySerializer;
44 private final SerializerDefinition valueSerializer;
45 private final SerializerDefinition transformsSerializer;
46 private final RoutingTier routingPolicy;
47 private final int replicationFactor;
48 private final Integer preferredWrites;
49 private final int requiredWrites;
50 private final Integer preferredReads;
51 private final int requiredReads;
52 private final Integer retentionPeriodDays;
53 private final Integer retentionScanThrottleRate;
54 private final Integer retentionFrequencyDays;
55 private final String routingStrategyType;
56 private final String viewOf;
57 private final HashMap<Integer, Integer> zoneReplicationFactor;
58 private final Integer zoneCountReads;
59 private final Integer zoneCountWrites;
60 private final String valueTransformation;
61 private final String serializerFactory;
62 private final HintedHandoffStrategyType hintedHandoffStrategyType;
63 private final Integer hintPrefListSize;
64 private final List<String> owners;
65 private final long memoryFootprintMB;
67 public StoreDefinition(String name,
68 String type,
69 String description,
70 SerializerDefinition keySerializer,
71 SerializerDefinition valueSerializer,
72 SerializerDefinition transformsSerializer,
73 RoutingTier routingPolicy,
74 String routingStrategyType,
75 int replicationFactor,
76 Integer preferredReads,
77 int requiredReads,
78 Integer preferredWrites,
79 int requiredWrites,
80 String viewOfStore,
81 String valTrans,
82 HashMap<Integer, Integer> zoneReplicationFactor,
83 Integer zoneCountReads,
84 Integer zoneCountWrites,
85 Integer retentionDays,
86 Integer retentionThrottleRate,
87 Integer retentionFrequencyDays,
88 String factory,
89 HintedHandoffStrategyType hintedHandoffStrategyType,
90 Integer hintPrefListSize,
91 List<String> owners,
92 long memoryFootprintMB) {
93 this.name = Utils.notNull(name);
94 this.type = type;
95 this.description = description;
96 this.replicationFactor = replicationFactor;
97 this.preferredReads = preferredReads;
98 this.requiredReads = requiredReads;
99 this.preferredWrites = preferredWrites;
100 this.requiredWrites = requiredWrites;
101 this.routingPolicy = routingPolicy;
102 this.keySerializer = keySerializer;
103 this.valueSerializer = valueSerializer;
104 this.transformsSerializer = transformsSerializer;
105 this.retentionPeriodDays = retentionDays;
106 this.retentionScanThrottleRate = retentionThrottleRate;
107 this.retentionFrequencyDays = retentionFrequencyDays;
108 this.memoryFootprintMB = memoryFootprintMB;
109 this.routingStrategyType = routingStrategyType;
110 this.viewOf = viewOfStore;
111 this.valueTransformation = valTrans;
112 this.zoneReplicationFactor = zoneReplicationFactor;
113 this.zoneCountReads = zoneCountReads;
114 this.zoneCountWrites = zoneCountWrites;
115 this.serializerFactory = factory;
116 this.hintedHandoffStrategyType = hintedHandoffStrategyType;
117 this.hintPrefListSize = hintPrefListSize;
118 this.owners = owners;
121 private void throwIllegalException(String errorMessage) {
122 throw new IllegalArgumentException(" Store '" + this.name + "'. Error: " + errorMessage);
125 protected void checkParameterLegality() {
127 // null checks
128 Utils.notNull(this.type);
129 Utils.notNull(routingPolicy);
130 Utils.notNull(keySerializer);
131 Utils.notNull(valueSerializer);
133 if(requiredReads < 1)
134 throwIllegalException("Cannot have a requiredReads number less than 1.");
135 else if(requiredReads > replicationFactor)
136 throwIllegalException("Cannot have more requiredReads then there are replicas.");
138 if(requiredWrites < 1)
139 throwIllegalException("Cannot have a requiredWrites number less than 1.");
140 else if(requiredWrites > replicationFactor)
141 throwIllegalException("Cannot have more requiredWrites then there are replicas.");
143 if(preferredWrites != null) {
144 if(preferredWrites < requiredWrites)
145 throwIllegalException("preferredWrites must be greater or equal to requiredWrites.");
146 if(preferredWrites > replicationFactor)
147 throwIllegalException("Cannot have more preferredWrites then there are replicas.");
149 if(preferredReads != null) {
150 if(preferredReads < requiredReads)
151 throwIllegalException("preferredReads must be greater or equal to requiredReads.");
152 if(preferredReads > replicationFactor)
153 throwIllegalException("Cannot have more preferredReads then there are replicas.");
156 if(retentionPeriodDays != null && retentionPeriodDays < 0)
157 throwIllegalException("Retention days must be non-negative.");
159 if(!SystemStoreConstants.isSystemStore(name) && zoneReplicationFactor != null
160 && zoneReplicationFactor.size() != 0) {
162 if(zoneCountReads == null || zoneCountReads < 0)
163 throwIllegalException("Zone Counts reads must be non-negative / non-null");
165 if(zoneCountWrites == null || zoneCountWrites < 0)
166 throwIllegalException("Zone Counts writes must be non-negative");
168 int sumZoneReplicationFactor = 0;
169 int replicatingZones = 0;
170 for(Integer zoneId: zoneReplicationFactor.keySet()) {
171 int currentZoneRepFactor = zoneReplicationFactor.get(zoneId);
173 sumZoneReplicationFactor += currentZoneRepFactor;
174 if(currentZoneRepFactor > 0)
175 replicatingZones++;
178 if(replicatingZones <= 0) {
179 throwIllegalException("Cannot have no zones to replicate to. "
180 + "Should have some positive zoneReplicationFactor");
183 // Check if sum of individual zones is equal to total replication
184 // factor
185 if(sumZoneReplicationFactor != replicationFactor) {
186 throwIllegalException("Sum total of zones (" + sumZoneReplicationFactor
187 + ") does not match the total replication factor ("
188 + replicationFactor + ")");
191 // Check if number of zone-count-reads and zone-count-writes are
192 // less than zones replicating to
193 if(zoneCountReads >= replicatingZones) {
194 throwIllegalException("Number of zones to block for while reading ("
195 + zoneCountReads
196 + ") should be less then replicating zones ("
197 + replicatingZones + ")");
200 if(zoneCountWrites >= replicatingZones) {
201 throwIllegalException("Number of zones to block for while writing ("
202 + zoneCountWrites
203 + ") should be less then replicating zones ("
204 + replicatingZones + ")");
209 public String getDescription() {
210 return this.description;
213 public String getSerializerFactory() {
214 return this.serializerFactory;
217 public boolean hasTransformsSerializer() {
218 return transformsSerializer != null;
221 public String getName() {
222 return name;
225 public int getRequiredWrites() {
226 return requiredWrites;
229 public SerializerDefinition getKeySerializer() {
230 return keySerializer;
233 public SerializerDefinition getValueSerializer() {
234 return valueSerializer;
237 public SerializerDefinition getTransformsSerializer() {
238 return transformsSerializer;
241 public RoutingTier getRoutingPolicy() {
242 return this.routingPolicy;
245 public int getReplicationFactor() {
246 return this.replicationFactor;
249 public String getRoutingStrategyType() {
250 return routingStrategyType;
253 public int getRequiredReads() {
254 return this.requiredReads;
257 public boolean hasPreferredWrites() {
258 return preferredWrites != null;
261 public int getPreferredWrites() {
262 return preferredWrites == null ? getRequiredWrites() : preferredWrites;
265 public int getPreferredReads() {
266 return preferredReads == null ? getRequiredReads() : preferredReads;
269 public boolean hasPreferredReads() {
270 return preferredReads != null;
273 public String getType() {
274 return type;
277 public boolean hasRetentionPeriod() {
278 return this.retentionPeriodDays != null && this.retentionPeriodDays > 0;
281 public Integer getRetentionDays() {
282 return this.retentionPeriodDays;
285 public boolean hasRetentionScanThrottleRate() {
286 return this.retentionScanThrottleRate != null;
289 public Integer getRetentionScanThrottleRate() {
290 return this.retentionScanThrottleRate;
293 public boolean hasRetentionFrequencyDays() {
294 return this.retentionFrequencyDays != null;
297 public Integer getRetentionFrequencyDays() {
298 return this.retentionFrequencyDays;
301 public boolean isView() {
302 return this.viewOf != null;
305 public String getViewTargetStoreName() {
306 return viewOf;
309 public boolean hasValueTransformation() {
310 return this.valueTransformation != null;
313 public String getValueTransformation() {
314 return valueTransformation;
317 public HashMap<Integer, Integer> getZoneReplicationFactor() {
318 return zoneReplicationFactor;
321 public Integer getZoneCountReads() {
322 return zoneCountReads;
325 public boolean hasZoneCountReads() {
326 return zoneCountReads != null;
329 public Integer getZoneCountWrites() {
330 return zoneCountWrites;
333 public boolean hasZoneCountWrites() {
334 return zoneCountWrites != null;
337 public HintedHandoffStrategyType getHintedHandoffStrategyType() {
338 return hintedHandoffStrategyType;
341 public boolean hasHintedHandoffStrategyType() {
342 return hintedHandoffStrategyType != null;
345 public Integer getHintPrefListSize() {
346 return hintPrefListSize;
349 public boolean hasHintPreflistSize() {
350 return hintPrefListSize != null;
353 public List<String> getOwners() {
354 return this.owners;
357 public long getMemoryFootprintMB() {
358 return this.memoryFootprintMB;
361 public boolean hasMemoryFootprint() {
362 return memoryFootprintMB != 0;
366 * When making changes, always make sure {@link #equals(Object)}, {@link #hashCode()} and
367 * {@link #diff(StoreDefinition, String, String)} behave consistently.
369 * @param o other {@link Object} to compare against.
370 * @return true if this instance equals the other instance, false otherwise.
372 @Override
373 public boolean equals(Object o) {
374 if(this == o)
375 return true;
376 else if(o == null)
377 return false;
378 else if(!(o.getClass() == StoreDefinition.class))
379 return false;
381 StoreDefinition def = (StoreDefinition) o;
382 return getName().equals(def.getName())
383 && getType().equals(def.getType())
384 && getReplicationFactor() == def.getReplicationFactor()
385 && getRequiredReads() == def.getRequiredReads()
386 && Objects.equal(getPreferredReads(), def.getPreferredReads())
387 && getRequiredWrites() == def.getRequiredWrites()
388 && Objects.equal(getPreferredWrites(), def.getPreferredWrites())
389 && getKeySerializer().equals(def.getKeySerializer())
390 && getValueSerializer().equals(def.getValueSerializer())
391 && Objects.equal(getTransformsSerializer() != null ? getTransformsSerializer() : null,
392 def.getTransformsSerializer() != null ? def.getTransformsSerializer() : null)
393 && getRoutingPolicy() == def.getRoutingPolicy()
394 && Objects.equal(getViewTargetStoreName(), def.getViewTargetStoreName())
395 // FIXME: This comparison is irrelevant, but not changing it in case it breaks something...
396 && Objects.equal(getValueTransformation() != null ? getValueTransformation().getClass() : null,
397 def.getValueTransformation() != null ? def.getValueTransformation().getClass() : null)
398 // FIXME: This comparison is irrelevant, but not changing it in case it breaks something...
399 && Objects.equal(getZoneReplicationFactor() != null ? getZoneReplicationFactor().getClass() : null,
400 def.getZoneReplicationFactor() != null ? def.getZoneReplicationFactor().getClass() : null)
401 && Objects.equal(getZoneCountReads(), def.getZoneCountReads())
402 && Objects.equal(getZoneCountWrites(), def.getZoneCountWrites())
403 && Objects.equal(getRetentionDays(), def.getRetentionDays())
404 && Objects.equal(getRetentionScanThrottleRate(), def.getRetentionScanThrottleRate())
405 && Objects.equal(getSerializerFactory() != null ? getSerializerFactory() : null,
406 def.getSerializerFactory() != null ? def.getSerializerFactory() : null)
407 && Objects.equal(getHintedHandoffStrategyType(), def.getHintedHandoffStrategyType())
408 && Objects.equal(getHintPrefListSize(), def.getHintPrefListSize())
409 && Objects.equal(getMemoryFootprintMB(), def.getMemoryFootprintMB());
413 * When making changes, always make sure {@link #equals(Object)}, {@link #hashCode()} and
414 * {@link #diff(StoreDefinition, String, String)} behave consistently.
416 @Override
417 public int hashCode() {
418 return Objects.hashCode(getName(),
419 getType(),
420 getDescription(),
421 getKeySerializer(),
422 getValueSerializer(),
423 getTransformsSerializer(),
424 getRoutingPolicy(),
425 getRoutingStrategyType(),
426 getReplicationFactor(),
427 getRequiredReads(),
428 getRequiredWrites(),
429 getPreferredReads(),
430 getPreferredWrites(),
431 getViewTargetStoreName(),
432 // FIXME: This comparison is irrelevant, but not changing it in case it breaks something...
433 getValueTransformation() == null ? null : getValueTransformation().getClass(),
434 // FIXME: This comparison is irrelevant, but not changing it in case it breaks something...
435 getZoneReplicationFactor() == null ? null : getZoneReplicationFactor().getClass(),
436 getZoneCountReads(),
437 getZoneCountWrites(),
438 getRetentionDays(),
439 getRetentionScanThrottleRate(),
440 getSerializerFactory(),
441 hasHintedHandoffStrategyType() ? getHintedHandoffStrategyType() : null,
442 hasHintPreflistSize() ? getHintPrefListSize() : null,
443 getOwners(),
444 getMemoryFootprintMB());
447 @Override
448 public String toString() {
449 return "StoreDefinition(name = " + getName() + ", type = " + getType() + ", description = "
450 + getDescription() + ", key-serializer = " + getKeySerializer()
451 + ", value-serializer = " + getValueSerializer() + ", routing = "
452 + getRoutingPolicy() + ", routing-strategy = " + getRoutingStrategyType()
453 + ", replication = " + getReplicationFactor() + ", required-reads = "
454 + getRequiredReads() + ", preferred-reads = " + getPreferredReads()
455 + ", required-writes = " + getRequiredWrites() + ", preferred-writes = "
456 + getPreferredWrites() + ", view-target = " + getViewTargetStoreName()
457 + ", value-transformation = " + getValueTransformation() + ", retention-days = "
458 + getRetentionDays() + ", throttle-rate = " + getRetentionScanThrottleRate()
459 + ", zone-replication-factor = " + getZoneReplicationFactor()
460 + ", zone-count-reads = " + getZoneCountReads() + ", zone-count-writes = "
461 + getZoneCountWrites() + ", serializer factory = " + getSerializerFactory() + ")"
462 + ", hinted-handoff-strategy = " + getHintedHandoffStrategyType()
463 + ", hint-preflist-size = " + getHintPrefListSize() + ", owners = " + getOwners()
464 + ", memory-footprint(MB) = " + getMemoryFootprintMB() + ")";
468 * Calls {@link #diff(StoreDefinition, "this", "other")}
470 * @param other StoreDefinition to compare against.
471 * @return a String containing information about differences between this StoreDefinition and the other one.
473 public String diff(StoreDefinition other) {
474 return diff(other, "this", "other");
478 * When making changes, always make sure {@link #equals(Object)}, {@link #hashCode()} and
479 * {@link #diff(StoreDefinition, String, String)} behave consistently.
481 * @param other StoreDefinition to compare against.
482 * @param thisName The name to be printed to identify this StoreDefinition instance.
483 * @param otherName The name to be printed to identify the other StoreDefinition instance.
484 * @return a String containing information about differences between this StoreDefinition and the other one.
486 public String diff(StoreDefinition other, String thisName, String otherName) {
487 if (this.equals(other)) {
488 return "StoreDefinitions are identical.";
489 } else {
490 StringBuilder sb = new StringBuilder();
491 if (!this.getName().equals(other.getName())) {
492 addToDiff("Name", this.getName(), other.getName(), sb, thisName, otherName);
494 if (!this.getType().equals(other.getType())) {
495 addToDiff("Type", this.getType(), other.getType(), sb, thisName, otherName);
497 if (this.getReplicationFactor() != other.getReplicationFactor()) {
498 addToDiff("Replication factor", this.getReplicationFactor(), other.getReplicationFactor(), sb, thisName, otherName);
500 if (this.getRequiredReads() != other.getRequiredReads()) {
501 addToDiff("Required reads", this.getRequiredReads(), other.getRequiredReads(), sb, thisName, otherName);
503 if (!Objects.equal(this.getPreferredReads(), other.getPreferredReads())) {
504 addToDiff("Preferred reads", this.getPreferredReads(), other.getPreferredReads(), sb, thisName, otherName);
506 if (this.getRequiredWrites() != other.getRequiredWrites()) {
507 addToDiff("Required writes", this.getRequiredWrites(), other.getRequiredWrites(), sb, thisName, otherName);
509 if (!Objects.equal(this.getPreferredWrites(), other.getPreferredWrites())) {
510 addToDiff("Preferred writes", this.getPreferredWrites(), other.getPreferredWrites(), sb, thisName, otherName);
512 if (!this.getKeySerializer().equals(other.getKeySerializer())) {
513 addToDiff("Key serializer", this.getKeySerializer().toString(), other.getKeySerializer().toString(), sb, thisName, otherName);
515 if (!this.getValueSerializer().equals(other.getValueSerializer())) {
516 addToDiff("Value serializer", this.getValueSerializer().toString(), other.getValueSerializer().toString(), sb, thisName, otherName);
518 if (!Objects.equal(this.getTransformsSerializer() != null ? this.getTransformsSerializer(): null,
519 other.getTransformsSerializer() != null ? other.getTransformsSerializer(): null)) {
520 // FIXME: This ternary operator is useless. Leaving it as is for consistency with equals().
521 addToDiff("Transforms Serializer", this.getTransformsSerializer().toString(), other.getTransformsSerializer().toString(), sb, thisName, otherName);
523 if (this.getRoutingPolicy() != other.getRoutingPolicy()) {
524 addToDiff("Routing policy", this.getRoutingPolicy().toDisplay(), other.getRoutingPolicy().toDisplay(), sb, thisName, otherName);
526 if (!Objects.equal(this.getViewTargetStoreName(), other.getViewTargetStoreName())) {
527 addToDiff("View target store name", this.getViewTargetStoreName(), other.getViewTargetStoreName(), sb, thisName, otherName);
529 if (!Objects.equal(this.getValueTransformation() != null ? this.getValueTransformation().getClass(): null,
530 other.getValueTransformation() != null ? other.getValueTransformation().getClass() : null)) {
531 // FIXME: This class comparison is irrelevant since it's always a String. Leaving it as is for consistency with equals().
532 addToDiff("Value transformation", this.getValueTransformation(), other.getValueTransformation(), sb, thisName, otherName);
534 if (!Objects.equal(this.getZoneReplicationFactor() != null ? this.getZoneReplicationFactor().getClass(): null,
535 other.getZoneReplicationFactor() != null ? other.getZoneReplicationFactor().getClass(): null)) {
536 // FIXME: This class comparison is irrelevant since it's always a HashMap. Leaving it as is for consistency with equals().
537 addToDiff("Zone replication factor", this.getZoneReplicationFactor().toString(), other.getZoneReplicationFactor().toString(), sb, thisName, otherName);
539 if (!Objects.equal(this.getZoneCountReads(), other.getZoneCountReads())) {
540 addToDiff("Zone count reads", this.getZoneCountReads(), other.getZoneCountReads(), sb, thisName, otherName);
542 if (!Objects.equal(this.getZoneCountWrites(), other.getZoneCountWrites())) {
543 addToDiff("Zone count writes", this.getZoneCountWrites(), other.getZoneCountWrites(), sb, thisName, otherName);
545 if (!Objects.equal(this.getRetentionDays(), other.getRetentionDays())) {
546 addToDiff("Retention days", this.getRetentionDays(), other.getRetentionDays(), sb, thisName, otherName);
548 if (!Objects.equal(this.getRetentionScanThrottleRate(), other.getRetentionScanThrottleRate())) {
549 addToDiff("Retention scan throttle rate", this.getRetentionScanThrottleRate(), other.getRetentionScanThrottleRate(), sb, thisName, otherName);
551 if (!Objects.equal(this.getSerializerFactory() != null ? getSerializerFactory() : null,
552 other.getSerializerFactory() != null ? other.getSerializerFactory(): null)) {
553 addToDiff("Serialization Factory", this.getSerializerFactory(), other.getSerializerFactory(), sb, thisName, otherName);
555 if (!Objects.equal(this.getHintedHandoffStrategyType(), other.getHintedHandoffStrategyType())) {
556 addToDiff("Hinted handoff strategy", this.getHintedHandoffStrategyType().toDisplay(), other.getHintedHandoffStrategyType().toDisplay(), sb, thisName, otherName);
558 if (!Objects.equal(this.getHintPrefListSize(), other.getHintPrefListSize())) {
559 addToDiff("Hinted preference list size", this.getHintPrefListSize(), other.getHintPrefListSize(), sb, thisName, otherName);
561 if (!Objects.equal(this.getMemoryFootprintMB(), other.getMemoryFootprintMB())) {
562 addToDiff("Memory footprint (MB)", this.getMemoryFootprintMB(), other.getMemoryFootprintMB(), sb, thisName, otherName);
564 sb.append("All other properties are identical.");
565 return sb.toString();
569 private void addToDiff(String propertyName, long thisValue, long otherValue, StringBuilder sb, String thisName, String otherName) {
570 addToDiff(propertyName, Long.toString(thisValue), Long.toString(otherValue), sb, thisName, otherName);
573 private void addToDiff(String propertyName, int thisValue, int otherValue, StringBuilder sb, String thisName, String otherName) {
574 addToDiff(propertyName, Integer.toString(thisValue), Integer.toString(otherValue), sb, thisName, otherName);
577 private void addToDiff(String propertyName, String thisValue, String otherValue, StringBuilder sb, String thisName, String otherName) {
578 sb.append(propertyName);
579 sb.append(" differs:\n\t");
580 sb.append(thisName);
581 sb.append(":\t");
582 sb.append(thisValue);
583 sb.append("\n\t");
584 sb.append(otherName);
585 sb.append(":\t");
586 sb.append(otherValue);
587 sb.append("\n");