001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import java.util.Collections;
021import java.util.List;
022import java.util.Map;
023import java.util.stream.Collectors;
024import org.apache.hadoop.hbase.client.CompactionState;
025import org.apache.hadoop.hbase.util.Strings;
026import org.apache.yetus.audience.InterfaceAudience;
027
028import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
029import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
030
031import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
032import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
033import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
034import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
035
036@InterfaceAudience.Private
037public final class RegionMetricsBuilder {
038
039  public static List<RegionMetrics>
040    toRegionMetrics(AdminProtos.GetRegionLoadResponse regionLoadResponse) {
041    return regionLoadResponse.getRegionLoadsList().stream()
042      .map(RegionMetricsBuilder::toRegionMetrics).collect(Collectors.toList());
043  }
044
045  public static RegionMetrics toRegionMetrics(ClusterStatusProtos.RegionLoad regionLoadPB) {
046    return RegionMetricsBuilder
047      .newBuilder(regionLoadPB.getRegionSpecifier().getValue().toByteArray())
048      .setBloomFilterSize(new Size(regionLoadPB.getTotalStaticBloomSizeKB(), Size.Unit.KILOBYTE))
049      .setCompactedCellCount(regionLoadPB.getCurrentCompactedKVs())
050      .setCompactingCellCount(regionLoadPB.getTotalCompactingKVs())
051      .setCompletedSequenceId(regionLoadPB.getCompleteSequenceId())
052      .setDataLocality(regionLoadPB.hasDataLocality() ? regionLoadPB.getDataLocality() : 0.0f)
053      .setDataLocalityForSsd(
054        regionLoadPB.hasDataLocalityForSsd() ? regionLoadPB.getDataLocalityForSsd() : 0.0f)
055      .setBlocksLocalWeight(
056        regionLoadPB.hasBlocksLocalWeight() ? regionLoadPB.getBlocksLocalWeight() : 0)
057      .setBlocksLocalWithSsdWeight(
058        regionLoadPB.hasBlocksLocalWithSsdWeight() ? regionLoadPB.getBlocksLocalWithSsdWeight() : 0)
059      .setBlocksTotalWeight(regionLoadPB.getBlocksTotalWeight())
060      .setCompactionState(
061        ProtobufUtil.createCompactionStateForRegionLoad(regionLoadPB.getCompactionState()))
062      .setFilteredReadRequestCount(regionLoadPB.getFilteredReadRequestsCount())
063      .setStoreFileUncompressedDataIndexSize(
064        new Size(regionLoadPB.getTotalStaticIndexSizeKB(), Size.Unit.KILOBYTE))
065      .setLastMajorCompactionTimestamp(regionLoadPB.getLastMajorCompactionTs())
066      .setMemStoreSize(new Size(regionLoadPB.getMemStoreSizeMB(), Size.Unit.MEGABYTE))
067      .setReadRequestCount(regionLoadPB.getReadRequestsCount())
068      .setWriteRequestCount(regionLoadPB.getWriteRequestsCount())
069      .setStoreFileIndexSize(new Size(regionLoadPB.getStorefileIndexSizeKB(), Size.Unit.KILOBYTE))
070      .setStoreFileRootLevelIndexSize(
071        new Size(regionLoadPB.getRootIndexSizeKB(), Size.Unit.KILOBYTE))
072      .setStoreCount(regionLoadPB.getStores()).setStoreFileCount(regionLoadPB.getStorefiles())
073      .setStoreRefCount(regionLoadPB.getStoreRefCount())
074      .setMaxCompactedStoreFileRefCount(regionLoadPB.getMaxCompactedStoreFileRefCount())
075      .setStoreFileSize(new Size(regionLoadPB.getStorefileSizeMB(), Size.Unit.MEGABYTE))
076      .setStoreSequenceIds(regionLoadPB.getStoreCompleteSequenceIdList().stream()
077        .collect(Collectors.toMap(
078          (ClusterStatusProtos.StoreSequenceId s) -> s.getFamilyName().toByteArray(),
079          ClusterStatusProtos.StoreSequenceId::getSequenceId)))
080      .setUncompressedStoreFileSize(
081        new Size(regionLoadPB.getStoreUncompressedSizeMB(), Size.Unit.MEGABYTE))
082      .setRegionSizeMB(new Size(regionLoadPB.getRegionSizeMB(), Size.Unit.MEGABYTE))
083      .setCurrentRegionCachedRatio(regionLoadPB.getCurrentRegionCachedRatio()).build();
084  }
085
086  private static List<ClusterStatusProtos.StoreSequenceId>
087    toStoreSequenceId(Map<byte[], Long> ids) {
088    return ids.entrySet().stream()
089      .map(e -> ClusterStatusProtos.StoreSequenceId.newBuilder()
090        .setFamilyName(UnsafeByteOperations.unsafeWrap(e.getKey())).setSequenceId(e.getValue())
091        .build())
092      .collect(Collectors.toList());
093  }
094
095  public static ClusterStatusProtos.RegionLoad toRegionLoad(RegionMetrics regionMetrics) {
096    return ClusterStatusProtos.RegionLoad.newBuilder()
097      .setRegionSpecifier(HBaseProtos.RegionSpecifier.newBuilder()
098        .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME)
099        .setValue(UnsafeByteOperations.unsafeWrap(regionMetrics.getRegionName())).build())
100      .setTotalStaticBloomSizeKB((int) regionMetrics.getBloomFilterSize().get(Size.Unit.KILOBYTE))
101      .setCurrentCompactedKVs(regionMetrics.getCompactedCellCount())
102      .setTotalCompactingKVs(regionMetrics.getCompactingCellCount())
103      .setCompleteSequenceId(regionMetrics.getCompletedSequenceId())
104      .setDataLocality(regionMetrics.getDataLocality())
105      .setFilteredReadRequestsCount(regionMetrics.getFilteredReadRequestCount())
106      .setTotalStaticIndexSizeKB(
107        (int) regionMetrics.getStoreFileUncompressedDataIndexSize().get(Size.Unit.KILOBYTE))
108      .setLastMajorCompactionTs(regionMetrics.getLastMajorCompactionTimestamp())
109      .setMemStoreSizeMB((int) regionMetrics.getMemStoreSize().get(Size.Unit.MEGABYTE))
110      .setReadRequestsCount(regionMetrics.getReadRequestCount())
111      .setWriteRequestsCount(regionMetrics.getWriteRequestCount())
112      .setStorefileIndexSizeKB((long) regionMetrics.getStoreFileIndexSize().get(Size.Unit.KILOBYTE))
113      .setRootIndexSizeKB(
114        (int) regionMetrics.getStoreFileRootLevelIndexSize().get(Size.Unit.KILOBYTE))
115      .setStores(regionMetrics.getStoreCount()).setStorefiles(regionMetrics.getStoreFileCount())
116      .setStoreRefCount(regionMetrics.getStoreRefCount())
117      .setMaxCompactedStoreFileRefCount(regionMetrics.getMaxCompactedStoreFileRefCount())
118      .setStorefileSizeMB((int) regionMetrics.getStoreFileSize().get(Size.Unit.MEGABYTE))
119      .addAllStoreCompleteSequenceId(toStoreSequenceId(regionMetrics.getStoreSequenceId()))
120      .setStoreUncompressedSizeMB(
121        (int) regionMetrics.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE))
122      .setRegionSizeMB((int) regionMetrics.getRegionSizeMB().get(Size.Unit.MEGABYTE))
123      .setCurrentRegionCachedRatio(regionMetrics.getCurrentRegionCachedRatio()).build();
124  }
125
126  public static RegionMetricsBuilder newBuilder(byte[] name) {
127    return new RegionMetricsBuilder(name);
128  }
129
130  private final byte[] name;
131  private int storeCount;
132  private int storeFileCount;
133  private int storeRefCount;
134  private int maxCompactedStoreFileRefCount;
135  private long compactingCellCount;
136  private long compactedCellCount;
137  private Size storeFileSize = Size.ZERO;
138  private Size memStoreSize = Size.ZERO;
139  private Size indexSize = Size.ZERO;
140  private Size rootLevelIndexSize = Size.ZERO;
141  private Size uncompressedDataIndexSize = Size.ZERO;
142  private Size bloomFilterSize = Size.ZERO;
143  private Size uncompressedStoreFileSize = Size.ZERO;
144  private long writeRequestCount;
145  private long readRequestCount;
146  private long filteredReadRequestCount;
147  private long completedSequenceId;
148  private Map<byte[], Long> storeSequenceIds = Collections.emptyMap();
149  private float dataLocality;
150  private long lastMajorCompactionTimestamp;
151  private float dataLocalityForSsd;
152  private long blocksLocalWeight;
153  private long blocksLocalWithSsdWeight;
154  private long blocksTotalWeight;
155  private CompactionState compactionState;
156  private Size regionSizeMB = Size.ZERO;
157  private float currentRegionCachedRatio;
158
159  private RegionMetricsBuilder(byte[] name) {
160    this.name = name;
161  }
162
163  public RegionMetricsBuilder setStoreCount(int value) {
164    this.storeCount = value;
165    return this;
166  }
167
168  public RegionMetricsBuilder setStoreFileCount(int value) {
169    this.storeFileCount = value;
170    return this;
171  }
172
173  public RegionMetricsBuilder setStoreRefCount(int value) {
174    this.storeRefCount = value;
175    return this;
176  }
177
178  public RegionMetricsBuilder setMaxCompactedStoreFileRefCount(int value) {
179    this.maxCompactedStoreFileRefCount = value;
180    return this;
181  }
182
183  public RegionMetricsBuilder setCompactingCellCount(long value) {
184    this.compactingCellCount = value;
185    return this;
186  }
187
188  public RegionMetricsBuilder setCompactedCellCount(long value) {
189    this.compactedCellCount = value;
190    return this;
191  }
192
193  public RegionMetricsBuilder setStoreFileSize(Size value) {
194    this.storeFileSize = value;
195    return this;
196  }
197
198  public RegionMetricsBuilder setMemStoreSize(Size value) {
199    this.memStoreSize = value;
200    return this;
201  }
202
203  public RegionMetricsBuilder setStoreFileIndexSize(Size value) {
204    this.indexSize = value;
205    return this;
206  }
207
208  public RegionMetricsBuilder setStoreFileRootLevelIndexSize(Size value) {
209    this.rootLevelIndexSize = value;
210    return this;
211  }
212
213  public RegionMetricsBuilder setStoreFileUncompressedDataIndexSize(Size value) {
214    this.uncompressedDataIndexSize = value;
215    return this;
216  }
217
218  public RegionMetricsBuilder setBloomFilterSize(Size value) {
219    this.bloomFilterSize = value;
220    return this;
221  }
222
223  public RegionMetricsBuilder setUncompressedStoreFileSize(Size value) {
224    this.uncompressedStoreFileSize = value;
225    return this;
226  }
227
228  public RegionMetricsBuilder setWriteRequestCount(long value) {
229    this.writeRequestCount = value;
230    return this;
231  }
232
233  public RegionMetricsBuilder setReadRequestCount(long value) {
234    this.readRequestCount = value;
235    return this;
236  }
237
238  public RegionMetricsBuilder setFilteredReadRequestCount(long value) {
239    this.filteredReadRequestCount = value;
240    return this;
241  }
242
243  public RegionMetricsBuilder setCompletedSequenceId(long value) {
244    this.completedSequenceId = value;
245    return this;
246  }
247
248  public RegionMetricsBuilder setStoreSequenceIds(Map<byte[], Long> value) {
249    this.storeSequenceIds = value;
250    return this;
251  }
252
253  public RegionMetricsBuilder setDataLocality(float value) {
254    this.dataLocality = value;
255    return this;
256  }
257
258  public RegionMetricsBuilder setLastMajorCompactionTimestamp(long value) {
259    this.lastMajorCompactionTimestamp = value;
260    return this;
261  }
262
263  public RegionMetricsBuilder setDataLocalityForSsd(float value) {
264    this.dataLocalityForSsd = value;
265    return this;
266  }
267
268  public RegionMetricsBuilder setBlocksLocalWeight(long value) {
269    this.blocksLocalWeight = value;
270    return this;
271  }
272
273  public RegionMetricsBuilder setBlocksLocalWithSsdWeight(long value) {
274    this.blocksLocalWithSsdWeight = value;
275    return this;
276  }
277
278  public RegionMetricsBuilder setBlocksTotalWeight(long value) {
279    this.blocksTotalWeight = value;
280    return this;
281  }
282
283  public RegionMetricsBuilder setCompactionState(CompactionState compactionState) {
284    this.compactionState = compactionState;
285    return this;
286  }
287
288  public RegionMetricsBuilder setRegionSizeMB(Size value) {
289    this.regionSizeMB = value;
290    return this;
291  }
292
293  public RegionMetricsBuilder setCurrentRegionCachedRatio(float value) {
294    this.currentRegionCachedRatio = value;
295    return this;
296  }
297
298  public RegionMetrics build() {
299    return new RegionMetricsImpl(name, storeCount, storeFileCount, storeRefCount,
300      maxCompactedStoreFileRefCount, compactingCellCount, compactedCellCount, storeFileSize,
301      memStoreSize, indexSize, rootLevelIndexSize, uncompressedDataIndexSize, bloomFilterSize,
302      uncompressedStoreFileSize, writeRequestCount, readRequestCount, filteredReadRequestCount,
303      completedSequenceId, storeSequenceIds, dataLocality, lastMajorCompactionTimestamp,
304      dataLocalityForSsd, blocksLocalWeight, blocksLocalWithSsdWeight, blocksTotalWeight,
305      compactionState, regionSizeMB, currentRegionCachedRatio);
306  }
307
308  private static class RegionMetricsImpl implements RegionMetrics {
309    private final byte[] name;
310    private final int storeCount;
311    private final int storeFileCount;
312    private final int storeRefCount;
313    private final int maxCompactedStoreFileRefCount;
314    private final long compactingCellCount;
315    private final long compactedCellCount;
316    private final Size storeFileSize;
317    private final Size memStoreSize;
318    private final Size indexSize;
319    private final Size rootLevelIndexSize;
320    private final Size uncompressedDataIndexSize;
321    private final Size bloomFilterSize;
322    private final Size uncompressedStoreFileSize;
323    private final long writeRequestCount;
324    private final long readRequestCount;
325    private final long filteredReadRequestCount;
326    private final long completedSequenceId;
327    private final Map<byte[], Long> storeSequenceIds;
328    private final float dataLocality;
329    private final long lastMajorCompactionTimestamp;
330    private final float dataLocalityForSsd;
331    private final long blocksLocalWeight;
332    private final long blocksLocalWithSsdWeight;
333    private final long blocksTotalWeight;
334    private final CompactionState compactionState;
335    private final Size regionSizeMB;
336    private final float currentRegionCachedRatio;
337
338    RegionMetricsImpl(byte[] name, int storeCount, int storeFileCount, int storeRefCount,
339      int maxCompactedStoreFileRefCount, final long compactingCellCount, long compactedCellCount,
340      Size storeFileSize, Size memStoreSize, Size indexSize, Size rootLevelIndexSize,
341      Size uncompressedDataIndexSize, Size bloomFilterSize, Size uncompressedStoreFileSize,
342      long writeRequestCount, long readRequestCount, long filteredReadRequestCount,
343      long completedSequenceId, Map<byte[], Long> storeSequenceIds, float dataLocality,
344      long lastMajorCompactionTimestamp, float dataLocalityForSsd, long blocksLocalWeight,
345      long blocksLocalWithSsdWeight, long blocksTotalWeight, CompactionState compactionState,
346      Size regionSizeMB, float currentRegionCachedRatio) {
347      this.name = Preconditions.checkNotNull(name);
348      this.storeCount = storeCount;
349      this.storeFileCount = storeFileCount;
350      this.storeRefCount = storeRefCount;
351      this.maxCompactedStoreFileRefCount = maxCompactedStoreFileRefCount;
352      this.compactingCellCount = compactingCellCount;
353      this.compactedCellCount = compactedCellCount;
354      this.storeFileSize = Preconditions.checkNotNull(storeFileSize);
355      this.memStoreSize = Preconditions.checkNotNull(memStoreSize);
356      this.indexSize = Preconditions.checkNotNull(indexSize);
357      this.rootLevelIndexSize = Preconditions.checkNotNull(rootLevelIndexSize);
358      this.uncompressedDataIndexSize = Preconditions.checkNotNull(uncompressedDataIndexSize);
359      this.bloomFilterSize = Preconditions.checkNotNull(bloomFilterSize);
360      this.uncompressedStoreFileSize = Preconditions.checkNotNull(uncompressedStoreFileSize);
361      this.writeRequestCount = writeRequestCount;
362      this.readRequestCount = readRequestCount;
363      this.filteredReadRequestCount = filteredReadRequestCount;
364      this.completedSequenceId = completedSequenceId;
365      this.storeSequenceIds = Preconditions.checkNotNull(storeSequenceIds);
366      this.dataLocality = dataLocality;
367      this.lastMajorCompactionTimestamp = lastMajorCompactionTimestamp;
368      this.dataLocalityForSsd = dataLocalityForSsd;
369      this.blocksLocalWeight = blocksLocalWeight;
370      this.blocksLocalWithSsdWeight = blocksLocalWithSsdWeight;
371      this.blocksTotalWeight = blocksTotalWeight;
372      this.compactionState = compactionState;
373      this.regionSizeMB = regionSizeMB;
374      this.currentRegionCachedRatio = currentRegionCachedRatio;
375    }
376
377    @Override
378    public byte[] getRegionName() {
379      return name;
380    }
381
382    @Override
383    public int getStoreCount() {
384      return storeCount;
385    }
386
387    @Override
388    public int getStoreFileCount() {
389      return storeFileCount;
390    }
391
392    @Override
393    public int getStoreRefCount() {
394      return storeRefCount;
395    }
396
397    @Override
398    public int getMaxCompactedStoreFileRefCount() {
399      return maxCompactedStoreFileRefCount;
400    }
401
402    @Override
403    public Size getStoreFileSize() {
404      return storeFileSize;
405    }
406
407    @Override
408    public Size getMemStoreSize() {
409      return memStoreSize;
410    }
411
412    @Override
413    public long getReadRequestCount() {
414      return readRequestCount;
415    }
416
417    @Override
418    public long getFilteredReadRequestCount() {
419      return filteredReadRequestCount;
420    }
421
422    @Override
423    public long getWriteRequestCount() {
424      return writeRequestCount;
425    }
426
427    @Override
428    public Size getStoreFileIndexSize() {
429      return indexSize;
430    }
431
432    @Override
433    public Size getStoreFileRootLevelIndexSize() {
434      return rootLevelIndexSize;
435    }
436
437    @Override
438    public Size getStoreFileUncompressedDataIndexSize() {
439      return uncompressedDataIndexSize;
440    }
441
442    @Override
443    public Size getBloomFilterSize() {
444      return bloomFilterSize;
445    }
446
447    @Override
448    public long getCompactingCellCount() {
449      return compactingCellCount;
450    }
451
452    @Override
453    public long getCompactedCellCount() {
454      return compactedCellCount;
455    }
456
457    @Override
458    public long getCompletedSequenceId() {
459      return completedSequenceId;
460    }
461
462    @Override
463    public Map<byte[], Long> getStoreSequenceId() {
464      return Collections.unmodifiableMap(storeSequenceIds);
465    }
466
467    @Override
468    public Size getUncompressedStoreFileSize() {
469      return uncompressedStoreFileSize;
470    }
471
472    @Override
473    public float getDataLocality() {
474      return dataLocality;
475    }
476
477    @Override
478    public long getLastMajorCompactionTimestamp() {
479      return lastMajorCompactionTimestamp;
480    }
481
482    @Override
483    public float getDataLocalityForSsd() {
484      return dataLocalityForSsd;
485    }
486
487    @Override
488    public long getBlocksLocalWeight() {
489      return blocksLocalWeight;
490    }
491
492    @Override
493    public long getBlocksLocalWithSsdWeight() {
494      return blocksLocalWithSsdWeight;
495    }
496
497    @Override
498    public long getBlocksTotalWeight() {
499      return blocksTotalWeight;
500    }
501
502    @Override
503    public CompactionState getCompactionState() {
504      return compactionState;
505    }
506
507    @Override
508    public Size getRegionSizeMB() {
509      return regionSizeMB;
510    }
511
512    @Override
513    public float getCurrentRegionCachedRatio() {
514      return currentRegionCachedRatio;
515    }
516
517    @Override
518    public String toString() {
519      StringBuilder sb =
520        Strings.appendKeyValue(new StringBuilder(), "storeCount", this.getStoreCount());
521      Strings.appendKeyValue(sb, "storeFileCount", this.getStoreFileCount());
522      Strings.appendKeyValue(sb, "storeRefCount", this.getStoreRefCount());
523      Strings.appendKeyValue(sb, "maxCompactedStoreFileRefCount",
524        this.getMaxCompactedStoreFileRefCount());
525      Strings.appendKeyValue(sb, "uncompressedStoreFileSize", this.getUncompressedStoreFileSize());
526      Strings.appendKeyValue(sb, "lastMajorCompactionTimestamp",
527        this.getLastMajorCompactionTimestamp());
528      Strings.appendKeyValue(sb, "storeFileSize", this.getStoreFileSize());
529      if (this.getUncompressedStoreFileSize().get() != 0) {
530        Strings.appendKeyValue(sb, "compressionRatio",
531          String.format("%.4f", (float) this.getStoreFileSize().get(Size.Unit.MEGABYTE)
532            / (float) this.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE)));
533      }
534      Strings.appendKeyValue(sb, "memStoreSize", this.getMemStoreSize());
535      Strings.appendKeyValue(sb, "readRequestCount", this.getReadRequestCount());
536      Strings.appendKeyValue(sb, "writeRequestCount", this.getWriteRequestCount());
537      Strings.appendKeyValue(sb, "rootLevelIndexSize", this.getStoreFileRootLevelIndexSize());
538      Strings.appendKeyValue(sb, "uncompressedDataIndexSize",
539        this.getStoreFileUncompressedDataIndexSize());
540      Strings.appendKeyValue(sb, "bloomFilterSize", this.getBloomFilterSize());
541      Strings.appendKeyValue(sb, "compactingCellCount", this.getCompactingCellCount());
542      Strings.appendKeyValue(sb, "compactedCellCount", this.getCompactedCellCount());
543      float compactionProgressPct = Float.NaN;
544      if (this.getCompactingCellCount() > 0) {
545        compactionProgressPct =
546          ((float) this.getCompactedCellCount() / (float) this.getCompactingCellCount());
547      }
548      Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
549      Strings.appendKeyValue(sb, "completedSequenceId", this.getCompletedSequenceId());
550      Strings.appendKeyValue(sb, "dataLocality", this.getDataLocality());
551      Strings.appendKeyValue(sb, "dataLocalityForSsd", this.getDataLocalityForSsd());
552      Strings.appendKeyValue(sb, "blocksLocalWeight", blocksLocalWeight);
553      Strings.appendKeyValue(sb, "blocksLocalWithSsdWeight", blocksLocalWithSsdWeight);
554      Strings.appendKeyValue(sb, "blocksTotalWeight", blocksTotalWeight);
555      Strings.appendKeyValue(sb, "compactionState", compactionState);
556      Strings.appendKeyValue(sb, "regionSizeMB", regionSizeMB);
557      Strings.appendKeyValue(sb, "currentRegionCachedRatio", currentRegionCachedRatio);
558      return sb.toString();
559    }
560  }
561
562}