mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

vharseko
13.39.2017 a10aa8bfa057bed239080486519604df44c8256e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2010 Sun Microsystems, Inc.
 * Portions copyright 2011-2016 ForgeRock AS.
 */
package org.forgerock.opendj.grizzly;
 
import java.io.IOException;
 
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.glassfish.grizzly.memory.PooledMemoryManager;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
import org.glassfish.grizzly.strategies.SameThreadIOStrategy;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
 
import com.forgerock.opendj.util.ReferenceCountedObject;
 
/**
 * The default {@link TCPNIOTransport} which all {@code LDAPConnectionFactory}s
 * and {@code LDAPListener}s will use unless otherwise specified in their
 * options.
 */
final class ServerTCPNIOTransport extends ReferenceCountedObject<TCPNIOTransport> {
 
    private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
    static final ServerTCPNIOTransport SERVER_TRANSPORT = new ServerTCPNIOTransport();
    private static final long MB = 1024 * 1024;
 
    private ServerTCPNIOTransport() {
        // Prevent instantiation.
    }
 
    @Override
    protected void destroyInstance(final TCPNIOTransport instance) {
        try {
            instance.shutdownNow();
        } catch (final IOException e) {
            // TODO: I18N
            logger.warn(LocalizableMessage.raw("An error occurred while shutting down the Grizzly transport", e));
        }
    }
 
    @Override
    protected TCPNIOTransport newInstance() {
        final TCPNIOTransportBuilder builder = TCPNIOTransportBuilder.newInstance();
 
        builder.setIOStrategy(SameThreadIOStrategy.getInstance());
 
        // Calculate thread counts.
        final int cpus = Runtime.getRuntime().availableProcessors();
 
        // Calculate the number of selector threads.
        final String selectorsStr = System.getProperty("org.forgerock.opendj.transport.selectors");
        final int selectorThreadCount;
 
        if (selectorsStr != null) {
            selectorThreadCount = Integer.parseInt(selectorsStr);
        } else {
            selectorThreadCount = Math.max(5, (cpus / 2) - 1);
        }
 
        builder.setSelectorThreadPoolConfig(
                ThreadPoolConfig.defaultConfig()
                                .setCorePoolSize(selectorThreadCount)
                                .setMaxPoolSize(selectorThreadCount)
                                .setPoolName("OpenDJ LDAP SDK Grizzly selector thread"));
 
        // Parse IO related options.
        final String lingerStr = System.getProperty("org.forgerock.opendj.transport.linger");
        if (lingerStr != null) {
            // Disabled by default.
            builder.setLinger(Integer.parseInt(lingerStr));
        }
 
        final String tcpNoDelayStr =
                System.getProperty("org.forgerock.opendj.transport.tcpNoDelay");
        if (tcpNoDelayStr != null) {
            // Enabled by default.
            builder.setTcpNoDelay(Boolean.parseBoolean(tcpNoDelayStr));
        }
 
        final String reuseAddressStr =
                System.getProperty("org.forgerock.opendj.transport.reuseAddress");
        if (reuseAddressStr != null) {
            // Enabled by default.
            builder.setReuseAddress(Boolean.parseBoolean(reuseAddressStr));
        }
        float heapPercent;
        if (Runtime.getRuntime().maxMemory() < 1024 * MB) {
            // Low heap
            heapPercent = 0.01f;
        } else {
            // Compute a percentage to try to reach roughly 64Mb (big enough (tm))
            heapPercent = 64f * MB / Runtime.getRuntime().maxMemory();
        }
        // Force usage of PooledMemoryManager which allows to use grizzly's buffers across threads.
        builder.setMemoryManager(new PooledMemoryManager(
                1024,  // Initial buffer size
                3,     // Number of pools (with growing factor below this give us pools of 1K, 4K, 16k buffers)
                4,     // Growing factor to apply on the size of the buffer polled by the next pool
                selectorThreadCount,    // Number of pool slices that every pool will stripe allocation requests across
                heapPercent, // The percentage of the heap that this manager will use when populating the pools (5%)
                1f,    // The percentage of buffers to be pre-allocated during MemoryManager initialization (100%)
                true   // true to use direct buffers or false to use heap buffers
        ));
 
        final TCPNIOTransport transport = builder.build();
 
        // FIXME: raise bug in Grizzly. We should not need to do this, but
        // failure to do so causes many deadlocks.
        transport.setSelectorRunnersCount(selectorThreadCount);
        try {
            transport.start();
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
 
        return transport;
    }
 
}