Skip to content

Commit

Permalink
Throttle StoreFileBean calls to prevent excessive resources consumption
Browse files Browse the repository at this point in the history
  • Loading branch information
andreikoval committed Jan 21, 2019
1 parent fe85a91 commit bf1e826
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 60 deletions.
184 changes: 134 additions & 50 deletions community/jmx/src/main/java/org/neo4j/jmx/impl/StoreFileBean.java
Expand Up @@ -20,8 +20,7 @@
package org.neo4j.jmx.impl; package org.neo4j.jmx.impl;


import java.io.File; import java.io.File;
import java.io.IOException; import java.time.Clock;
import javax.management.NotCompliantMBeanException;


import org.neo4j.helpers.Service; import org.neo4j.helpers.Service;
import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction;
Expand All @@ -32,6 +31,8 @@
import org.neo4j.kernel.impl.transaction.log.files.LogFiles; import org.neo4j.kernel.impl.transaction.log.files.LogFiles;
import org.neo4j.kernel.impl.transaction.state.DataSourceManager; import org.neo4j.kernel.impl.transaction.state.DataSourceManager;


import static org.neo4j.jmx.impl.StoreSizeBean.resolveStorePath;
import static org.neo4j.jmx.impl.ThrottlingBeanSnapshotProxy.newThrottlingBeanSnapshotProxy;
import static org.neo4j.kernel.impl.store.StoreFactory.NODE_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.NODE_STORE_NAME;
import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_ARRAYS_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_ARRAYS_STORE_NAME;
import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_STORE_NAME;
Expand All @@ -41,70 +42,153 @@
@Service.Implementation( ManagementBeanProvider.class ) @Service.Implementation( ManagementBeanProvider.class )
public final class StoreFileBean extends ManagementBeanProvider public final class StoreFileBean extends ManagementBeanProvider
{ {
@SuppressWarnings( "WeakerAccess" ) // Bean needs public constructor private static final long UPDATE_INTERVAL = 60000;
private static final StoreFile NO_STORE_FILE = new StoreFile()
{
@Override
public long getLogicalLogSize()
{
return 0;
}

@Override
public long getTotalStoreSize()
{
return 0;
}

@Override
public long getNodeStoreSize()
{
return 0;
}

@Override
public long getRelationshipStoreSize()
{
return 0;
}

@Override
public long getPropertyStoreSize()
{
return 0;
}

@Override
public long getStringStoreSize()
{
return 0;
}

@Override
public long getArrayStoreSize()
{
return 0;
}
};

public StoreFileBean() public StoreFileBean()
{ {
super( StoreFile.class ); super( StoreFile.class );
} }


@Override @Override
protected Neo4jMBean createMBean( ManagementData management ) throws NotCompliantMBeanException protected Neo4jMBean createMBean( ManagementData management )
{ {
return new StoreFileImpl( management ); final StoreFileMBean bean = new StoreFileMBean( management );
final DataSourceManager dataSourceManager = management.resolveDependency( DataSourceManager.class );
dataSourceManager.addListener( bean );
return bean;
} }


static class StoreFileImpl extends Neo4jMBean implements StoreFile static class StoreFileMBean extends Neo4jMBean implements StoreFile, DataSourceManager.Listener
{
private final FileSystemAbstraction fs;
private final File storePath;
private volatile StoreFile delegate = NO_STORE_FILE;

StoreFileMBean( ManagementData management )
{
super( management, false );
this.fs = management.getKernelData().getFilesystemAbstraction();
this.storePath = resolveStorePath( management );
}

@Override
public void registered( NeoStoreDataSource ds )
{
final LogFiles logFiles = ds.getDependencyResolver().resolveDependency( LogFiles.class );
final StoreFileImpl dataProvider = new StoreFileImpl( fs, storePath, logFiles );
this.delegate = newThrottlingBeanSnapshotProxy( StoreFile.class, dataProvider, UPDATE_INTERVAL, Clock.systemUTC() );
}

@Override
public void unregistered( NeoStoreDataSource ds )
{
this.delegate = NO_STORE_FILE;
}

@Override
public long getLogicalLogSize()
{
return delegate.getLogicalLogSize();
}

@Override
public long getTotalStoreSize()
{
return delegate.getTotalStoreSize();
}

@Override
public long getNodeStoreSize()
{
return delegate.getNodeStoreSize();
}

@Override
public long getRelationshipStoreSize()
{
return delegate.getRelationshipStoreSize();
}

@Override
public long getPropertyStoreSize()
{
return delegate.getPropertyStoreSize();
}

@Override
public long getStringStoreSize()
{
return delegate.getStringStoreSize();
}

@Override
public long getArrayStoreSize()
{
return delegate.getArrayStoreSize();
}
}

static class StoreFileImpl implements StoreFile
{ {
private static final String NODE_STORE = MetaDataStore.DEFAULT_NAME + NODE_STORE_NAME; private static final String NODE_STORE = MetaDataStore.DEFAULT_NAME + NODE_STORE_NAME;
private static final String RELATIONSHIP_STORE = MetaDataStore.DEFAULT_NAME + RELATIONSHIP_STORE_NAME; private static final String RELATIONSHIP_STORE = MetaDataStore.DEFAULT_NAME + RELATIONSHIP_STORE_NAME;
private static final String PROPERTY_STORE = MetaDataStore.DEFAULT_NAME + PROPERTY_STORE_NAME; private static final String PROPERTY_STORE = MetaDataStore.DEFAULT_NAME + PROPERTY_STORE_NAME;
private static final String ARRAY_STORE = MetaDataStore.DEFAULT_NAME + PROPERTY_ARRAYS_STORE_NAME; private static final String ARRAY_STORE = MetaDataStore.DEFAULT_NAME + PROPERTY_ARRAYS_STORE_NAME;
private static final String STRING_STORE = MetaDataStore.DEFAULT_NAME + PROPERTY_STRINGS_STORE_NAME; private static final String STRING_STORE = MetaDataStore.DEFAULT_NAME + PROPERTY_STRINGS_STORE_NAME;


private File storePath; private final File storePath;
private LogFiles logFiles; private final LogFiles logFiles;
private FileSystemAbstraction fs; private final FileSystemAbstraction fs;


StoreFileImpl( ManagementData management ) throws NotCompliantMBeanException StoreFileImpl( FileSystemAbstraction fs, File storePath, LogFiles logFiles )
{ {
super( management ); this.fs = fs;

this.storePath = storePath;
fs = management.getKernelData().getFilesystemAbstraction(); this.logFiles = logFiles;

DataSourceManager dataSourceManager = management.resolveDependency( DataSourceManager.class );
dataSourceManager.addListener( new DataSourceManager.Listener()
{
@Override
public void registered( NeoStoreDataSource ds )
{
logFiles = resolveDependency( ds, LogFiles.class );
storePath = resolvePath( ds );
}

private <T> T resolveDependency( NeoStoreDataSource ds, Class<T> clazz )
{
return ds.getDependencyResolver().resolveDependency( clazz );
}

@Override
public void unregistered( NeoStoreDataSource ds )
{
logFiles = null;
storePath = null;
}

private File resolvePath( NeoStoreDataSource ds )
{
try
{
return ds.getStoreDir().getCanonicalFile().getAbsoluteFile();
}
catch ( IOException e )
{
return ds.getStoreDir().getAbsoluteFile();
}
}
} );
} }


@Override @Override
Expand Down
20 changes: 10 additions & 10 deletions community/jmx/src/main/java/org/neo4j/jmx/impl/StoreSizeBean.java
Expand Up @@ -257,18 +257,18 @@ public long getTotalStoreSize()
{ {
return delegate.getTotalStoreSize(); return delegate.getTotalStoreSize();
} }
}


private static File resolveStorePath( ManagementData management ) static File resolveStorePath( ManagementData management )
{
File storeDir = management.getKernelData().getStoreDir();
try
{ {
File storeDir = management.getKernelData().getStoreDir(); return storeDir.getCanonicalFile().getAbsoluteFile();
try }
{ catch ( IOException e )
return storeDir.getCanonicalFile().getAbsoluteFile(); {
} return storeDir.getAbsoluteFile();
catch ( IOException e )
{
return storeDir.getAbsoluteFile();
}
} }
} }


Expand Down

0 comments on commit bf1e826

Please sign in to comment.