/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.internal.util.ipc.shmem; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.management.ManagementFactory; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.util.typedef.internal.U; /** * NOTE: Native library should be loaded, before methods of this class are called. * Native library is loaded with: {@link IpcSharedMemoryNativeLoader#load(org.apache.ignite.IgniteLogger)}. */ public class IpcSharedMemoryUtils { /** * Allocates shared memory segment and semaphores for IPC exchange. * * @param tokFileName OS token file name. * @param size Memory space size in bytes. * @param debug {@code True} to output debug to stdout (will set global flag). * @return Shared memory pointer. * @throws IgniteCheckedException If failed. */ static native long allocateSystemResources(String tokFileName, int size, boolean debug) throws IgniteCheckedException; /** * Attaches to previously allocated shared memory segment. * * @param shmemId OS shared memory segment ID. * @param debug {@code True} to output debug to stdout (will set global flag). * @return Shared memory pointer. * @throws IgniteCheckedException If failed. */ static native long attach(int shmemId, boolean debug) throws IgniteCheckedException; /** * Stops IPC communication. Call {@link #freeSystemResources(String, long, boolean)} after this call. * * @param shmemPtr Shared memory pointer. */ static native void ipcClose(long shmemPtr); /** * Frees system resources. * * @param tokFileName Token file name. * @param shmemPtr Shared memory pointer * @param force {@code True} to force close. */ static native void freeSystemResources(String tokFileName, long shmemPtr, boolean force); /** * Frees system resources. * * @param tokFileName Token file name. * @param size Size. */ static native void freeSystemResources(String tokFileName, int size); /** * @param shMemPtr Shared memory pointer. * @param dest Destination buffer. * @param dOff Destination offset. * @param size Size. * @param timeout Operation timeout. * @return Read bytes count. * @throws IgniteCheckedException If space has been closed. * @throws IpcSharedMemoryOperationTimedoutException If operation times out. */ static native long readSharedMemory(long shMemPtr, byte dest[], long dOff, long size, long timeout) throws IgniteCheckedException, IpcSharedMemoryOperationTimedoutException; /** * @param shmemPtr Shared memory pointer. * @return Unread count. */ static native int unreadCount(long shmemPtr); /** * @param shmemPtr Shared memory pointer. * @return Shared memory ID. */ static native int sharedMemoryId(long shmemPtr); /** * @param shmemPtr Shared memory pointer. * @return Semaphore set ID. */ static native int semaphoreId(long shmemPtr); /** * @param shMemPtr Shared memory pointer * @param dest Destination buffer. * @param dOff Destination offset. * @param size Size. * @param timeout Operation timeout. * @return Read bytes count. * @throws IgniteCheckedException If space has been closed. * @throws IpcSharedMemoryOperationTimedoutException If operation times out. */ static native long readSharedMemoryByteBuffer(long shMemPtr, ByteBuffer dest, long dOff, long size, long timeout) throws IgniteCheckedException, IpcSharedMemoryOperationTimedoutException; /** * @param shMemPtr Shared memory pointer * @param src Source buffer. * @param sOff Offset. * @param size Size. * @param timeout Operation timeout. * @throws IgniteCheckedException If space has been closed. * @throws IpcSharedMemoryOperationTimedoutException If operation times out. */ static native void writeSharedMemory(long shMemPtr, byte src[], long sOff, long size, long timeout) throws IgniteCheckedException, IpcSharedMemoryOperationTimedoutException; /** * @param shMemPtr Shared memory pointer * @param src Source buffer. * @param sOff Offset. * @param size Size. * @param timeout Operation timeout. * @throws IgniteCheckedException If space has been closed. * @throws IpcSharedMemoryOperationTimedoutException If operation times out. */ static native void writeSharedMemoryByteBuffer(long shMemPtr, ByteBuffer src, long sOff, long size, long timeout) throws IgniteCheckedException, IpcSharedMemoryOperationTimedoutException; /** @return PID of the current process (-1 on error). */ public static int pid() { // Should be something like this: 1160@mbp.local String name = ManagementFactory.getRuntimeMXBean().getName(); try { int idx = name.indexOf('@'); return idx > 0 ? Integer.parseInt(name.substring(0, idx)) : -1; } catch (NumberFormatException ignored) { return -1; } } /** * @param pid PID to check. * @return {@code True} if process with passed ID is alive. */ static native boolean alive(int pid); /** * Returns shared memory ids for Mac OS and Linux platforms. * * @return Collection of all shared memory IDs in the system. * @throws IOException If failed. * @throws InterruptedException If failed. * @throws IllegalStateException If current OS is not supported. */ static Collection<Integer> sharedMemoryIds() throws IOException, InterruptedException { if (U.isMacOs() || U.isLinux()) return sharedMemoryIdsOnMacOS(); else throw new IllegalStateException("Current OS is not supported."); } /** * @param e Link error. * @return Wrapping grid exception. */ static IgniteCheckedException linkError(UnsatisfiedLinkError e) { return new IgniteCheckedException("Linkage error due to possible native library, libigniteshmem.so, " + "version mismatch (stop all grid nodes, clean up your '/tmp' folder, and try again).", e); } /** * @return Shared memory IDs. * @throws IOException If failed. * @throws InterruptedException If failed. */ private static Collection<Integer> sharedMemoryIdsOnMacOS() throws IOException, InterruptedException { // IPC status from <running system> as of Mon Jan 21 15:33:54 MSK 2013 // T ID KEY MODE OWNER GROUP // Shared Memory: // m 327680 0x4702fd26 --rw-rw-rw- yzhdanov staff Process proc = Runtime.getRuntime().exec("ipcs -m"); BufferedReader rdr = new BufferedReader(new InputStreamReader(proc.getInputStream())); Collection<Integer> ret = new ArrayList<>(); try { String line; while ((line = rdr.readLine()) != null) { if (!line.startsWith(getPlatformDependentLineStartFlag())) continue; String[] toks = line.split(" "); try { ret.add(Integer.parseInt(toks[1])); } catch (NumberFormatException ignored) { // No-op (just ignore). } } return ret; } finally { proc.waitFor(); } } /** @return Flag for {@code ipcs} utility. */ private static String getPlatformDependentLineStartFlag() { if (U.isMacOs()) return "m "; else if (U.isLinux()) return "0x"; else throw new IllegalStateException("This OS is not supported."); } }