public LocalMultiMapStats createStats(String name) {
    LocalMultiMapStatsImpl stats = getLocalMultiMapStatsImpl(name);
    long ownedEntryCount = 0;
    long backupEntryCount = 0;
    long hits = 0;
    long lockedEntryCount = 0;
    ClusterServiceImpl clusterService = (ClusterServiceImpl) nodeEngine.getClusterService();

    Address thisAddress = clusterService.getThisAddress();
    for (int i = 0; i < nodeEngine.getPartitionService().getPartitionCount(); i++) {
      InternalPartition partition = nodeEngine.getPartitionService().getPartition(i);
      MultiMapPartitionContainer partitionContainer = getPartitionContainer(i);
      MultiMapContainer multiMapContainer = partitionContainer.getCollectionContainer(name);
      if (multiMapContainer == null) {
        continue;
      }
      Address owner = partition.getOwnerOrNull();
      if (owner != null) {
        if (owner.equals(thisAddress)) {
          lockedEntryCount += multiMapContainer.getLockedCount();
          for (MultiMapWrapper wrapper : multiMapContainer.getMultiMapWrappers().values()) {
            hits += wrapper.getHits();
            ownedEntryCount += wrapper.getCollection(false).size();
          }
        } else {
          int backupCount = multiMapContainer.getConfig().getTotalBackupCount();
          for (int j = 1; j <= backupCount; j++) {
            Address replicaAddress = partition.getReplicaAddress(j);
            int memberSize = nodeEngine.getClusterService().getMembers().size();

            int tryCount = REPLICA_ADDRESS_TRY_COUNT;
            // wait if the partition table is not updated yet
            while (memberSize > backupCount && replicaAddress == null && tryCount-- > 0) {
              try {
                Thread.sleep(REPLICA_ADDRESS_SLEEP_WAIT_MILLIS);
              } catch (InterruptedException e) {
                throw ExceptionUtil.rethrow(e);
              }
              replicaAddress = partition.getReplicaAddress(j);
            }

            if (replicaAddress != null && replicaAddress.equals(thisAddress)) {
              for (MultiMapWrapper wrapper : multiMapContainer.getMultiMapWrappers().values()) {
                backupEntryCount += wrapper.getCollection(false).size();
              }
            }
          }
        }
      }
    }
    stats.setOwnedEntryCount(ownedEntryCount);
    stats.setBackupEntryCount(backupEntryCount);
    stats.setHits(hits);
    stats.setLockedEntryCount(lockedEntryCount);
    return stats;
  }
 public void insertMigratedData(int partitionId, Map<String, Map> map) {
   for (Map.Entry<String, Map> entry : map.entrySet()) {
     String name = entry.getKey();
     MultiMapContainer container = getOrCreateCollectionContainer(partitionId, name);
     Map<Data, MultiMapWrapper> collections = entry.getValue();
     long maxRecordId = -1;
     for (Map.Entry<Data, MultiMapWrapper> wrapperEntry : collections.entrySet()) {
       MultiMapWrapper wrapper = wrapperEntry.getValue();
       container.getMultiMapWrappers().put(wrapperEntry.getKey(), wrapper);
       long wrapperMaxRecordId = getMaxRecordId(wrapper);
       maxRecordId = Math.max(maxRecordId, wrapperMaxRecordId);
     }
     container.setId(maxRecordId);
   }
 }
 @Override
 public Operation prepareReplicationOperation(PartitionReplicationEvent event) {
   int replicaIndex = event.getReplicaIndex();
   final MultiMapPartitionContainer partitionContainer =
       partitionContainers[event.getPartitionId()];
   if (partitionContainer == null) {
     return null;
   }
   Map<String, Map> map = new HashMap<String, Map>(partitionContainer.containerMap.size());
   for (Map.Entry<String, MultiMapContainer> entry : partitionContainer.containerMap.entrySet()) {
     String name = entry.getKey();
     MultiMapContainer container = entry.getValue();
     if (container.getConfig().getTotalBackupCount() < replicaIndex) {
       continue;
     }
     map.put(name, container.getMultiMapWrappers());
   }
   if (map.isEmpty()) {
     return null;
   }
   return new MultiMapMigrationOperation(map);
 }