class GroupStateLazyStore {
        /** */
        private static final AtomicIntegerFieldUpdater<GroupStateLazyStore> initGuardUpdater =
            AtomicIntegerFieldUpdater.newUpdater(GroupStateLazyStore.class, "initGuard");

        /** Cache states. Initialized lazily. */
        @Nullable private volatile Map<Integer, GroupState> grpStates;

        /** */
        private final CountDownLatch latch;

        /** */
        @SuppressWarnings("unused")
        private volatile int initGuard;

        /** Initialization exception. */
        private IgniteCheckedException initEx;

        /**
         * Default constructor.
         */
        private GroupStateLazyStore() {
            this(null);
        }

        /**
         * Constructor with group state map.
         *
         * @param stateMap Group state map.
         */
        GroupStateLazyStore(@Nullable Map<Integer, GroupState> stateMap) {
            if (stateMap != null) {
                initGuard = 1;

                latch = new CountDownLatch(0);
            }
            else
                latch = new CountDownLatch(1);

            this.grpStates = stateMap;
        }

        /**
         * @param stateRec Cache group state.
         */
        private static Map<Integer, GroupState> remap(@NotNull Map<Integer, CacheState> stateRec) {<FILL_FUNCTION_BODY>}

        /**
         * @return Partitions' states by group id.
         */
        @Nullable Map<Integer, GroupState> groupStates() {
            return grpStates;
        }

        /**
         * @param grpId Group id.
         * @param part Partition id.
         * @return Partition counter.
         */
        private Long partitionCounter(int grpId, int part) {
            assert initGuard != 0 : initGuard;

            if (initEx != null || grpStates == null)
                return null;

            GroupState state = grpStates.get(grpId);

            if (state != null) {
                long cntr = state.counterByPartition(part);

                return cntr < 0 ? null : cntr;
            }

            return null;
        }

        /**
         * @param wal Write ahead log manager.
         * @param ptr Checkpoint wal pointer.
         * @throws IgniteCheckedException If failed to read WAL entry.
         */
        private void initIfNeeded(
            IgniteWriteAheadLogManager wal,
            WALPointer ptr
        ) throws IgniteCheckedException {
            if (initGuardUpdater.compareAndSet(this, 0, 1)) {
                try (WALIterator it = wal.replay(ptr)) {
                    if (it.hasNextX()) {
                        IgniteBiTuple<WALPointer, WALRecord> tup = it.nextX();

                        CheckpointRecord rec = (CheckpointRecord)tup.get2();

                        Map<Integer, CacheState> stateRec = rec.cacheGroupStates();

                        grpStates = remap(stateRec);
                    }
                    else {
                        throw new IgniteCheckedException(
                            "Failed to find checkpoint record at the given WAL pointer: " + ptr);
                    }
                }
                catch (IgniteCheckedException e) {
                    initEx = e;

                    throw e;
                }
                finally {
                    latch.countDown();
                }
            }
            else {
                U.await(latch);

                if (initEx != null)
                    throw initEx;
            }
        }
    }

            if (stateRec.isEmpty())
                return Collections.emptyMap();

            Map<Integer, GroupState> grpStates = U.newHashMap(stateRec.size());

            for (Integer grpId : stateRec.keySet()) {
                CacheState recState = stateRec.get(grpId);

                GroupState grpState = new GroupState(recState.size());

                for (int i = 0; i < recState.size(); i++) {
                    byte partState = recState.stateByIndex(i);

                    if (GridDhtPartitionState.fromOrdinal(partState) != GridDhtPartitionState.OWNING)
                        continue;

                    grpState.addPartitionCounter(
                        recState.partitionByIndex(i),
                        recState.partitionCounterByIndex(i)
                    );
                }

                grpStates.put(grpId, grpState);
            }

            return grpStates;
        
<no_super_class>