public CacheReplicationOperation(CachePartitionSegment segment, int replicaIndex) {
    data = new HashMap<String, Map<Data, CacheRecord>>();

    Iterator<ICacheRecordStore> iter = segment.cacheIterator();
    while (iter.hasNext()) {
      ICacheRecordStore cacheRecordStore = iter.next();
      CacheConfig cacheConfig = cacheRecordStore.getConfig();
      if (cacheConfig.getAsyncBackupCount() + cacheConfig.getBackupCount() >= replicaIndex) {
        data.put(cacheRecordStore.getName(), cacheRecordStore.getReadOnlyRecords());
      }
    }

    configs = new ArrayList<CacheConfig>(segment.getCacheConfigs());
  }
  @Override
  public void run() throws Exception {
    CacheService service = getService();
    for (Map.Entry<String, Map<Data, CacheRecord>> entry : data.entrySet()) {
      ICacheRecordStore cache = service.getOrCreateCache(entry.getKey(), getPartitionId());
      Map<Data, CacheRecord> map = entry.getValue();

      Iterator<Map.Entry<Data, CacheRecord>> iter = map.entrySet().iterator();
      while (iter.hasNext()) {
        Map.Entry<Data, CacheRecord> next = iter.next();
        Data key = next.getKey();
        CacheRecord record = next.getValue();
        iter.remove();
        cache.setRecord(key, record);
      }
    }
    data.clear();
  }
  @Override
  public void run() throws Exception {
    final int partitionId = getPartitionId();
    final InternalPartitionService partitionService = getNodeEngine().getPartitionService();

    Set<Data> filteredKeys = new HashSet<Data>();
    if (keys != null) {
      for (Data k : keys) {
        if (partitionService.getPartitionId(k) == partitionId) {
          filteredKeys.add(k);
        }
      }
    }

    if (filteredKeys.isEmpty()) {
      return;
    }

    try {
      final ICacheService service = getService();
      cache = service.getOrCreateRecordStore(name, partitionId);
      final Set<Data> keysLoaded = cache.loadAll(filteredKeys, replaceExistingValues);
      shouldBackup = !keysLoaded.isEmpty();
      if (shouldBackup) {
        backupRecords = new HashMap<Data, CacheRecord>(keysLoaded.size());
        for (Data key : keysLoaded) {
          CacheRecord record = cache.getRecord(key);
          // Loaded keys may have been evicted, then record will be null.
          // So if the loaded key is evicted, don't send it to backup.
          if (record != null) {
            backupRecords.put(key, record);
          }
        }
      }
    } catch (CacheException e) {
      response = new CacheClearResponse(e);
    }
  }
  protected void putAndGetFromCacheRecordStore(
      ICacheRecordStore cacheRecordStore, InMemoryFormat inMemoryFormat) {
    SerializationService serializationService = new DefaultSerializationServiceBuilder().build();

    for (int i = 0; i < CACHE_RECORD_COUNT; i++) {
      cacheRecordStore.put(serializationService.toData(i), "value-" + i, null, null, -1);
    }

    if (inMemoryFormat == InMemoryFormat.BINARY || inMemoryFormat == InMemoryFormat.NATIVE) {
      for (int i = 0; i < CACHE_RECORD_COUNT; i++) {
        assertTrue(
            Data.class.isAssignableFrom(
                cacheRecordStore.get(serializationService.toData(i), null).getClass()));
      }
    } else if (inMemoryFormat == InMemoryFormat.OBJECT) {
      for (int i = 0; i < CACHE_RECORD_COUNT; i++) {
        assertTrue(
            String.class.isAssignableFrom(
                cacheRecordStore.get(serializationService.toData(i), null).getClass()));
      }
    } else {
      throw new IllegalArgumentException("Unsupported in-memory format: " + inMemoryFormat);
    }
  }
 @Override
 public final int getAsyncBackupCount() {
   return cache != null ? cache.getConfig().getAsyncBackupCount() : 0;
 }