All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.crankuptheamps.client.PublishStore Maven / Gradle / Ivy

////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010-2024 60East Technologies Inc., All Rights Reserved.
//
// This computer software is owned by 60East Technologies Inc. and is
// protected by U.S. copyright laws and other laws and by international
// treaties.  This computer software is furnished by 60East Technologies
// Inc. pursuant to a written license agreement and may be used, copied,
// transmitted, and stored only in accordance with the terms of such
// license agreement and with the inclusion of the above copyright notice.
// This computer software or any other copies thereof may not be provided
// or otherwise made available to any other person.
//
// U.S. Government Restricted Rights.  This computer software: (a) was
// developed at private expense and is in all respects the proprietary
// information of 60East Technologies Inc.; (b) was not developed with
// government funds; (c) is a trade secret of 60East Technologies Inc.
// for all purposes of the Freedom of Information Act; and (d) is a
// commercial item and thus, pursuant to Section 12.212 of the Federal
// Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
// Government's use, duplication or disclosure of the computer software
// is subject to the restrictions set forth by 60East Technologies Inc..
//
////////////////////////////////////////////////////////////////////////////

package com.crankuptheamps.client;

import com.crankuptheamps.client.exception.*;
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * PublishStore is a memory-mapped file-backed store for storing outgoing
 * messages. As messages are stored, space is allocated from a pre-created flat
 * buffer on disk. As messages are discarded, space in that buffer is marked
 * "free" for future store operations. If messages are stored faster than they
 * are published, the buffer is re-sized to create more capacity.
 * PublishStore helps in keeping track of unacknowledged messages.
 * If messages are published at a rate exceeding the storage capacity,
 * the buffer is resized to accommodate more messages.
 * 

* The PublishStore class provides a robust foundation for implementing features * such as tracking unacknowledged messages and ensuring message persistence. *

*/ public class PublishStore extends BlockPublishStore { // Constants and variables final static int DEFAULT_INITIAL_BLOCKS = 10 * 1000; private int _initialCapacity; private boolean _truncateOnClose = false; // MMapStoreBuffer class is a nested class for managing memory-mapped // storage. static class MMapStoreBuffer extends MemoryStoreBuffer { String _path; RandomAccessFile _file; FileChannel _channel; // Constructor for MMapStoreBuffer public MMapStoreBuffer(String path) throws StoreException { _path = path; try { _file = new RandomAccessFile(path, "rw"); } catch (IOException e) { throw new StoreException(e); } _channel = _file.getChannel(); } // Retrieves the current size of the storage buffer @Override public long getSize() throws IOException { if (_buffer == null) { if (_file.length() == 0) { return 0; } _buffer = _channel.map(MapMode.READ_WRITE, 0, _file.length()); } return _buffer.capacity(); } // Sets the size of the storage buffer. This can be used to resize the buffer // when needed @Override public void setSize(long newSize) throws IOException { if (_channel == null) { throw new IOException("The store is closed."); } if (_buffer != null) ((MappedByteBuffer) _buffer).force(); _buffer = _channel.map(MapMode.READ_WRITE, 0, newSize); } // Close and release resources associated with the memory-mapped storage public void close() throws Exception { _buffer = null; _store = null; if (_channel != null) _channel.close(); if (_file != null) _file.close(); _channel = null; _file = null; } // Forces data synchronization to ensure any changes made to the memory-mapped // storage are flushed to disk public void sync() throws IOException { MappedByteBuffer b = ((MappedByteBuffer) _buffer); b.force(); } // Finalize method for cleanup @Override protected void finalize() throws Throwable { close(); super.finalize(); } } /** * Creates a new PublishStore with the given path. Immediately proceeds to * recovery if the file exists. * @param path The path (absolute or relative) of the publish store * @throws StoreException Thrown when an operation on the store fails. */ public PublishStore(String path) throws StoreException { this(path, DEFAULT_INITIAL_BLOCKS); } /** * Creates a new PublishStore with the given path. Immediately proceeds to recovery * if the file exists. * @param path The path (absolute or relative) of the publish store * @param initialCapacity The initial capacity (in 2k blocks) of the store. This * size is also used when resizing the store: the store * is resized by this value each time the store grows. A * general guideline for initial capacity is to set the * capacity to messages_published_per_second * * int(average_message_size / block_size) + * 1. * @throws StoreException Thrown when an operation on the store fails. */ public PublishStore(String path, int initialCapacity) throws StoreException { super(new MMapStoreBuffer(path), initialCapacity, true); _initialCapacity = initialCapacity; recover(); if (_usedList == null) { growFreeListIfEmpty(); } } /** * Tells the PublishStore to truncate the file to its original size if there are no saved Messages when it is closed. * This feature is not supported on Windows. * @param truncate If true, file will be truncated when the PublishStore is * closed. */ public void truncateOnClose(boolean truncate) { _truncateOnClose = truncate; } /** * Closes the memory mapped file. * @throws IOException Thrown when an operation on the file produces an IOException. */ public void close() throws Exception { if (_buffer == null) return; // Calculate the count of unpersisted (unsaved) messages long unpersistedCount = unpersistedCount(); _buffer.close(); if (_truncateOnClose && unpersistedCount == 0 && !System.getProperty("os.name").startsWith("Windows")) { FileChannel channel = new FileOutputStream(((MMapStoreBuffer) _buffer)._path, true).getChannel(); channel.truncate((long) _initialCapacity * BlockPublishStore.Block.SIZE); } _buffer = null; } /** * Forces any in memory changes to be written to persistent storage. This * method ensures that any unsaved modifications are committed to the * underlying file. * @throws IOException Thrown when an operation on the file produces an * IOException. */ public void sync() throws IOException { ((MMapStoreBuffer) _buffer).sync(); } /** * Overridden to call close() upon garbage collection. */ @Override protected void finalize() throws Throwable { close(); super.finalize(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy