Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
Merge pull request #697 from sonatype/nxcm-4852
Browse files Browse the repository at this point in the history
NXCM-4852: EOF on deploy
  • Loading branch information
cstamas authored and peterlynch committed Dec 12, 2012
1 parent 67c3488 commit 24a7be5
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 2 deletions.
@@ -0,0 +1,40 @@
/*
* Sonatype Nexus (TM) Open Source Version
* Copyright (c) 2007-2012 Sonatype, Inc.
* All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
* which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
* of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
* Eclipse Foundation. All other trademarks are the property of their respective owners.
*/
package org.sonatype.nexus.proxy;

/**
* Local storage exception thrown by local storage when stream/content being pushed (stored) ends prematurely (EOFs).
* Denotes an unrecoverable state, but is not resolvable by Nexus core (happens when client drops connection
* during upload, recovery is to have client retry upload).
*
* @author cstamas
* @since 2.3
*/
public class LocalStorageEofException
extends LocalStorageException
{
public LocalStorageEofException( String msg )
{
super( msg );
}

public LocalStorageEofException( String msg, Throwable cause )
{
super( msg, cause );
}

public LocalStorageEofException( Throwable cause )
{
super( cause.getMessage(), cause );
}
}
Expand Up @@ -14,12 +14,12 @@

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.EOFException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand All @@ -31,11 +31,11 @@
import org.codehaus.plexus.util.IOUtil;
import org.sonatype.nexus.logging.AbstractLoggingComponent;
import org.sonatype.nexus.proxy.ItemNotFoundException;
import org.sonatype.nexus.proxy.LocalStorageEofException;
import org.sonatype.nexus.proxy.LocalStorageException;
import org.sonatype.nexus.proxy.ResourceStoreRequest;
import org.sonatype.nexus.proxy.access.Action;
import org.sonatype.nexus.proxy.item.ContentLocator;
import org.sonatype.nexus.proxy.item.RepositoryItemUid;
import org.sonatype.nexus.proxy.item.RepositoryItemUidLock;
import org.sonatype.nexus.proxy.item.StorageItem;
import org.sonatype.nexus.proxy.item.uid.IsItemAttributeMetacontentAttribute;
Expand Down Expand Up @@ -113,6 +113,17 @@ public void storeItem( final Repository repository, final File repositoryBaseDir

os.flush();
}
catch ( EOFException e )
{
if ( hiddenTarget != null )
{
hiddenTarget.delete();
}

throw new LocalStorageEofException( String.format(
"EOF during storing on path \"%s\" (while writing to hiddenTarget: \"%s\")",
item.getRepositoryItemUid().toString(), hiddenTarget.getAbsolutePath() ), e );
}
catch ( IOException e )
{
if ( hiddenTarget != null )
Expand Down
Expand Up @@ -14,8 +14,14 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.emptyIterableOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

Expand All @@ -41,6 +47,7 @@
import org.sonatype.nexus.proxy.repository.GroupRepository;
import org.sonatype.nexus.proxy.repository.LocalStatus;
import org.sonatype.nexus.proxy.repository.Repository;
import org.sonatype.nexus.util.WrappingInputStream;

import com.google.common.base.Strings;

Expand Down Expand Up @@ -442,6 +449,68 @@ public void testNexus4985GroupsShouldNotSwallowMemberExceptions()
}
}

/**
* NXCM-4582: When Local storage is about to store something, but during "store" operation source stream EOFs,
* the new LocalStorage exception should be thrown, to differentiate from other "fatal" (like disk full or what not)
* error.
*/
@Test
public void testNXCM4852()
throws Exception
{
final Repository repository = getRepositoryRegistry().getRepository( "inhouse" );
ResourceStoreRequest request =
new ResourceStoreRequest( "/activemq/activemq-core/1.2/activemq-core-1.2.jar", true );

try
{
repository.storeItem( request, new WrappingInputStream(
new ByteArrayInputStream( "123456789012345678901234567890".getBytes() ) )
{
@Override
public int read()
throws IOException
{
int result = super.read();
if ( result == -1 )
{
throw new EOFException( "Foo" );
}
else
{
return result;
}
}

@Override
public int read( final byte[] b, final int off, final int len )
throws IOException
{
int result = super.read( b, off, len );
if ( result == -1 )
{
throw new EOFException( "Foo" );
}
return result;
}
}, null );

Assert.fail( "We expected a LocalStorageEofException to be thrown" );
}
catch ( LocalStorageEofException e )
{
// good, we expected this
}
finally
{
// now we have to ensure no remnant files exists
assertThat( repository.getLocalStorage().containsItem( repository, request ), is( false ) );
// no tmp files should exists either
assertThat( repository.getLocalStorage().listItems( repository, new ResourceStoreRequest( "/.nexus/tmp" ) ), is( empty() ) );
}
}


//

protected int countOccurence( final String string, final String snippet )
Expand Down
Expand Up @@ -50,6 +50,7 @@
import org.sonatype.nexus.proxy.IllegalOperationException;
import org.sonatype.nexus.proxy.IllegalRequestException;
import org.sonatype.nexus.proxy.ItemNotFoundException;
import org.sonatype.nexus.proxy.LocalStorageEofException;
import org.sonatype.nexus.proxy.NoSuchRepositoryException;
import org.sonatype.nexus.proxy.NoSuchResourceStoreException;
import org.sonatype.nexus.proxy.RemoteStorageTransportOverloadedException;
Expand Down Expand Up @@ -881,6 +882,14 @@ protected void handleException( final Request req, final Response res, final Exc
{
throw (ResourceException) t;
}
else if ( t instanceof LocalStorageEofException )
{
// in case client drops connection, this makes not much sense, as he will not
// receive this response, but we have to end it somehow.
// but, in case when remote proxy peer drops connection on us regularly
// this makes sense
throw new ResourceException( getStatus( Status.CLIENT_ERROR_NOT_FOUND, t ), t );
}
else if ( t instanceof IllegalArgumentException )
{
throw new ResourceException( getStatus( Status.CLIENT_ERROR_BAD_REQUEST, t ), t );
Expand Down

0 comments on commit 24a7be5

Please sign in to comment.