Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IdGenerator may generate duplicate IDs #7299

Closed
lukasblu opened this issue Jan 12, 2016 · 3 comments
Closed

IdGenerator may generate duplicate IDs #7299

lukasblu opened this issue Jan 12, 2016 · 3 comments
Assignees
Labels
Source: Community PR or issue was opened by a community user Team: Core Type: Defect
Milestone

Comments

@lukasblu
Copy link
Contributor

Hi,

it looks as if the IdGenerator may generate duplicate IDs if put under stress.

Here is a test to reproduce the issue. I tested it on a 3.5.5-SNAPSHOT from 2015-12-17.

Best,
Lukas

package com.nm.test.hazelcast.idgenerator;

import com.hazelcast.config.Config;
import com.hazelcast.config.XmlConfigBuilder;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IdGenerator;
import com.nm.test.hazelcast.TestHazelcast;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import junit.framework.TestCase;

/**
 * A test to ensure the ID generator does not produce duplicate IDs.
 */
public class TestIdGenerator1 extends TestCase {

    private static final Logger logger = Logger.getLogger(TestIdGenerator1.class);

    private static final String idGeneratorName = "idGen_" + TestIdGenerator1.class.getSimpleName();

    private static final int numThreads = 16;

    private static final int numIdsPerThread = 400001;

    @Override
    protected void setUp() throws Exception {

        // configure logging
        if (!TestHazelcast.loggingInitialized) {
            TestHazelcast.loggingInitialized = true;
            BasicConfigurator.configure();
        }
    }

    public void testConcurrentIdGenMulti() throws Exception {
        final int numRuns = 5;
        int numFailures = 0;
        for (int i = 0; i < numRuns; i++) {
            if (!testConcurrentIdGen(i)) {
                numFailures++;
            }
        }
        if (numFailures > 0) {
            fail("Duplicate IDs were generated in " + numFailures + " out of " + numRuns + " runs.");
        }
    }

    private boolean testConcurrentIdGen(int runIndex) throws Exception {

        // result
        final Set<Long> generatedIds = Collections.newSetFromMap(new ConcurrentHashMap<Long, Boolean>());

        // try-finally to terminate hazelcast instance
        HazelcastInstance hcInstance = null;
        try {

            // create config
            Config config = new XmlConfigBuilder().build();
            config.setProperty("hazelcast.logging.type", "log4j");
            config.setProperty("hazelcast.version.check.enabled", "false");

            // disable multicast for faster startup
            config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);

            // create hazelcast instance
            hcInstance = Hazelcast.newHazelcastInstance(config);

            // get and init ID generator
            final IdGenerator idGen = hcInstance.getIdGenerator(idGeneratorName + runIndex);
            idGen.init(13013L);

            // run with multiple threads in parallel
            List<Thread> threads = new ArrayList<Thread>();
            for (int threadIndex = 0; threadIndex < numThreads; threadIndex++) {
                final int threadIndexCur = threadIndex;

                Thread thread = new Thread(new Runnable() {

                    @Override
                    public void run() {

                        // generate IDs
                        logger.info("Thread " + threadIndexCur + " generating IDs...");
                        for (int i = 0; i < numIdsPerThread; i++) {
                            long newId = idGen.newId();
                            if (!generatedIds.add(newId)) {
                                logger.warn("Same ID generated: " + newId);
                            }
                        }
                        logger.info("Thread " + threadIndexCur + " generating IDs done.");
                    }

                }, "generator-thread-" + threadIndex);
                threads.add(thread);
            }

            // start and join
            for (Thread thread : threads) {
                thread.start();
            }
            for (Thread thread : threads) {
                thread.join();
            }
        } finally {
            if (hcInstance != null) {
                hcInstance.getLifecycleService().terminate();
            }
        }

        // ensure correct result
        long maxId = -1L;
        for (Long value : generatedIds) {
            if (value > maxId) {
                maxId = value;
            }
        }
        logger.info("Max ID = " + maxId);
        logger.info("Number of generated IDs = " + generatedIds.size());
        if (generatedIds.size() == numThreads * numIdsPerThread) {
            return true;
        } else {
            logger.warn("Same IDs generated!");
            return false;
        }
    }

}
@gurbuzali gurbuzali self-assigned this Jan 12, 2016
@gurbuzali gurbuzali added this to the 3.5.5 milestone Jan 12, 2016
@gurbuzali
Copy link
Contributor

Thank you for reporting, I've reproduced the issue and looking into it

@lukasblu
Copy link
Contributor Author

@gurbuzali Ps. the test also fails on the current master branch.

@eminn
Copy link
Contributor

eminn commented Jan 14, 2016

Forward-port : #7320

@mmedenjak mmedenjak added the Source: Community PR or issue was opened by a community user label Aug 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Source: Community PR or issue was opened by a community user Team: Core Type: Defect
Projects
None yet
Development

No branches or pull requests

4 participants