Skip to content

Commit 291d948

Browse files
committed
[GR-14763] Implement Internal gzcon.
PullRequest: fastr/1978
2 parents 8ff70a6 + 729443e commit 291d948

File tree

12 files changed

+258
-104
lines changed

12 files changed

+258
-104
lines changed

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1510,7 +1510,7 @@ public Object getSummaryDescription(Object x) {
15101510
@TruffleBoundary
15111511
public Object getConnectionClassString(Object x) {
15121512
BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class);
1513-
return wrapString(conn.getConnectionClass());
1513+
return wrapString(conn.getConnectionClassName());
15141514
}
15151515

15161516
@Override

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ public BasePackage() {
580580
add(GrepFunctions.Regexec.class, GrepFunctionsFactory.RegexecNodeGen::create);
581581
add(GrepFunctions.Strsplit.class, GrepFunctionsFactory.StrsplitNodeGen::create);
582582
add(GrepFunctions.Sub.class, GrepFunctionsFactory.SubNodeGen::create);
583+
add(GZCon.class, GZConNodeGen::create);
583584
add(HiddenInternalFunctions.GetRegisteredRoutines.class, HiddenInternalFunctionsFactory.GetRegisteredRoutinesNodeGen::create);
584585
add(HiddenInternalFunctions.ImportIntoEnv.class, HiddenInternalFunctionsFactory.ImportIntoEnvNodeGen::create);
585586
add(HiddenInternalFunctions.LazyLoadDBFetch.class, HiddenInternalFunctionsFactory.LazyLoadDBFetchNodeGen::create);

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ protected RList summary(int object) {
506506
BaseRConnection baseCon = RConnection.fromIndex(object);
507507
Object[] data = new Object[NAMES.getLength()];
508508
data[0] = baseCon.getSummaryDescription();
509-
data[1] = baseCon.getConnectionClass();
509+
data[1] = baseCon.getConnectionClassName();
510510
data[2] = baseCon.getOpenMode().summaryString();
511511
data[3] = baseCon.isTextMode() ? "text" : "binary";
512512
data[4] = baseCon.isOpen() ? "opened" : "closed";
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 3 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 3 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 3 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package com.oracle.truffle.r.nodes.builtin.base;
24+
25+
import com.oracle.truffle.api.dsl.Cached;
26+
import com.oracle.truffle.api.dsl.Specialization;
27+
import com.oracle.truffle.api.profiles.ConditionProfile;
28+
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
29+
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
30+
import static com.oracle.truffle.r.runtime.RCompression.Type.GZIP;
31+
import com.oracle.truffle.r.runtime.RError;
32+
import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
33+
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
34+
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
35+
import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
36+
import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
37+
import static com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass.GZCon;
38+
import com.oracle.truffle.r.runtime.conn.RConnection;
39+
import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
40+
import java.io.IOException;
41+
42+
@RBuiltin(name = "gzcon", kind = INTERNAL, parameterNames = {"con", "level", "allowNonCompressed", "text"}, behavior = PURE)
43+
public abstract class GZCon extends RBuiltinNode.Arg4 {
44+
45+
static {
46+
Casts casts = new Casts(GZCon.class);
47+
casts.arg("con").defaultError(RError.Message.NOT_CONNECTION, "con").mustNotBeNull().asIntegerVector().findFirst();
48+
casts.arg("level").asIntegerVector().findFirst();
49+
casts.arg("allowNonCompressed").asLogicalVector().findFirst().map(toBoolean());
50+
casts.arg("text").asLogicalVector().findFirst().map(toBoolean());
51+
}
52+
53+
@Specialization
54+
public RAbstractIntVector gzcon(int conIndex, @SuppressWarnings("unused") int level, @SuppressWarnings("unused") boolean allowNonCompressed, @SuppressWarnings("unused") boolean text,
55+
@Cached("createBinaryProfile()") ConditionProfile gzConProfile) {
56+
BaseRConnection base = RConnection.fromIndex(conIndex);
57+
if (gzConProfile.profile(base.getConnectionClass() == ConnectionClass.GZCon)) {
58+
RError.warning(this, RError.Message.IS_GZCON);
59+
return base.asVector();
60+
}
61+
try {
62+
base.setCompressiontype(GZIP);
63+
base.updateConnectionClass(GZCon);
64+
} catch (IOException ex) {
65+
throw error(RError.Message.GENERIC, ex.getMessage());
66+
}
67+
return base.asVector();
68+
}
69+
70+
}

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,8 @@ public enum Message {
10451045
DATE_TIME_CONVERSION_SPEC_NOT_IMPLEMENTED("Date time conversion format '%s' is not implemented in FastR yet. Please submit an issue at https://github.com/oracle/fastr."),
10461046
CANNOT_ALLOCATE_VECTOR_GB("cannot allocate vector of size %.1f Gb"),
10471047
INVALID_POLYNOMIAL_COEFFICIENT("invalid polynomial coefficient"),
1048-
ROOT_FINDING_FAILED("root finding code failed");
1048+
ROOT_FINDING_FAILED("root finding code failed"),
1049+
IS_GZCON("this is already a 'gzcon' connection");
10491050

10501051
public final String message;
10511052
final boolean hasArgs;

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@
4141

4242
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4343
import com.oracle.truffle.api.object.DynamicObject;
44+
import com.oracle.truffle.r.runtime.RCompression;
4445
import com.oracle.truffle.r.runtime.RError;
4546
import com.oracle.truffle.r.runtime.RError.Message;
4647
import com.oracle.truffle.r.runtime.RInternalError;
@@ -317,6 +318,7 @@ public enum ConnectionClass {
317318
Terminal("terminal"),
318319
File("file"),
319320
GZFile("gzfile"),
321+
GZCon("gzcon"),
320322
BZFile("bzfile"),
321323
XZFile("xzfile"),
322324
Socket("sockconn"),
@@ -641,7 +643,11 @@ private BaseRConnection(ConnectionClass conClass, OpenMode mode) {
641643
this.openMode = mode;
642644
}
643645

644-
public String getConnectionClass() {
646+
public ConnectionClass getConnectionClass() {
647+
return conClass;
648+
}
649+
650+
public String getConnectionClassName() {
645651
return conClass.getPrintName();
646652
}
647653

@@ -743,8 +749,12 @@ protected void checkOpen() {
743749
}
744750

745751
protected void setDelegate(DelegateRConnection conn) {
752+
setDelegate(conn, true);
753+
}
754+
755+
protected void setDelegate(DelegateRConnection conn, boolean opened) {
746756
this.theConnection = conn;
747-
opened = true;
757+
this.opened = opened;
748758
}
749759

750760
protected String[] readLinesInternal(int n, EnumSet<ReadLineWarning> warn, boolean skipNul) throws IOException {
@@ -865,6 +875,10 @@ public boolean isSeekable() {
865875
*/
866876
protected abstract void createDelegateConnection() throws IOException;
867877

878+
public void setCompressiontype(@SuppressWarnings("unused") RCompression.Type cType) throws IOException {
879+
throw new IOException();
880+
}
881+
868882
/**
869883
* Return the value that is used in the "description" field by {@code summary.connection}.
870884
*/
@@ -1061,7 +1075,7 @@ protected void setIncomplete(boolean b) {
10611075
}
10621076

10631077
public final RAbstractIntVector asVector() {
1064-
String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass(), "connection"};
1078+
String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClassName(), "connection"};
10651079

10661080
RAbstractIntVector result = RDataFactory.createIntVector(new int[]{getDescriptor()}, true);
10671081

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,8 @@
4747
import com.oracle.truffle.r.runtime.data.RDataFactory;
4848
import com.oracle.truffle.r.runtime.data.RObject;
4949
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
50+
import java.util.zip.GZIPInputStream;
51+
import java.util.zip.GZIPOutputStream;
5052

5153
/**
5254
* Actually performs the I/O operations for a connections.<br>
@@ -628,4 +630,81 @@ public void closeAndDestroy() throws IOException {
628630
base.closed = true;
629631
close();
630632
}
633+
634+
private static final int GZIP_BUFFER_SIZE = (2 << 20);
635+
636+
static DelegateRConnection createGZIPDelegateOutputConnection(BaseRConnection base, OutputStream os) throws IOException {
637+
assert base.getOpenMode().canWrite();
638+
return new CompressedOutputRConnection(base, new GZIPOutputStream(os, GZIP_BUFFER_SIZE), true);
639+
}
640+
641+
static DelegateRConnection createGZIPDelegateInputConnection(BaseRConnection base, InputStream is) throws IOException {
642+
assert base.getOpenMode().canRead();
643+
return new CompressedInputRConnection(base, new GZIPInputStream(is, GZIP_BUFFER_SIZE));
644+
}
645+
646+
static class CompressedOutputRConnection extends DelegateWriteRConnection {
647+
protected ByteChannel channel;
648+
private final boolean seekable;
649+
private long seekPosition = 0L;
650+
651+
protected CompressedOutputRConnection(BaseRConnection base, OutputStream os, boolean seekable) {
652+
super(base);
653+
this.seekable = seekable;
654+
this.channel = ConnectionSupport.newChannel(os);
655+
}
656+
657+
@Override
658+
public void closeAndDestroy() throws IOException {
659+
base.closed = true;
660+
close();
661+
}
662+
663+
@Override
664+
protected long seekInternal(long offset, RConnection.SeekMode seekMode, RConnection.SeekRWMode seekRWMode) throws IOException {
665+
if (seekable) {
666+
// TODO GZIP is basically seekable; however, the output stream does not allow any
667+
// seeking
668+
long oldPos = seekPosition;
669+
seekPosition = offset;
670+
return oldPos;
671+
}
672+
return super.seek(offset, seekMode, seekRWMode);
673+
}
674+
675+
@Override
676+
public boolean isSeekable() {
677+
return seekable;
678+
}
679+
680+
@Override
681+
public ByteChannel getChannel() {
682+
return channel;
683+
}
684+
685+
@Override
686+
public void truncate() throws IOException {
687+
throw RError.nyi(RError.SHOW_CALLER, "truncating compressed file not");
688+
}
689+
}
690+
691+
static class CompressedInputRConnection extends DelegateReadRConnection {
692+
private final ByteChannel channel;
693+
694+
protected CompressedInputRConnection(BaseRConnection base, InputStream is) {
695+
super(base);
696+
channel = ConnectionSupport.newChannel(is);
697+
}
698+
699+
@Override
700+
public ByteChannel getChannel() {
701+
return channel;
702+
}
703+
704+
@Override
705+
public boolean isSeekable() {
706+
return false;
707+
}
708+
}
709+
631710
}

0 commit comments

Comments
 (0)