--- a/ExternalStream.st Wed Mar 13 17:04:15 2019 +0100
+++ b/ExternalStream.st Wed Mar 13 17:08:50 2019 +0100
@@ -1897,7 +1897,7 @@
!ExternalStream class methodsFor:'defaults'!
-bufferSizeForBulkFileCopy
+bufferSizeForBulkCopy
"return the size of buffer used when copying big files/buld data from one stream to another.
Due to a bug on older Windows systems, the default used
is chosen very conservatively, as the copy used to fail with big buffers.
@@ -1911,14 +1911,16 @@
DefaultCopyBufferSize notNil ifTrue:[^ DefaultCopyBufferSize].
OperatingSystem isMSDOSlike ifTrue:[
- OperatingSystem isWin7Like ifTrue:[
- ^ 64*1024
- ] ifFalse:[
- "/ mhmh - NT hangs, when copying bigger blocks to a network drive - why ?
- ^ 1 * 1024.
- ].
+ OperatingSystem isWin7Like ifTrue:[
+ ^ 64*1024
+ ] ifFalse:[
+ "/ mhmh - NT hangs, when copying bigger blocks to a network drive - why ?
+ ^ 1 * 1024.
+ ].
].
^ 32 * 1024.
+
+ "Created: / 13-03-2019 / 16:49:17 / Stefan Vogel"
!
defaultCopyBufferSize:anInteger
@@ -3138,37 +3140,57 @@
"Modified: / 15.1.1998 / 11:49:48 / stefan"
!
-copyToEndFrom:inStream
- "read from inStream, and write all data up to the end to the receiver.
+copy:numberOfBytesOrNil into:outStream bufferSize:bufferSize
+ "read from the receiver, and write numberOfBytes data to another aWriteStream.
Return the number of bytes which have been transferred.
- Same functionality as copyToEnd:, but reversed arg and receiver
- (useful in a cascade message of the writeStream)"
-
- ^ inStream copyToEndInto:self bufferSize:(self class bufferSizeForBulkFileCopy)
+ If nuberOfBytesOrNil is nil, copy until the end of myself.
+ Redefined to use operating system features to do a fast copy."
+
+ |pos n nWritten|
+
+ outStream isExternalStream ifTrue:[
+ "sendfile() in Linux does not support any combination of file/pipe/socket fds.
+ #copyFromFd:toFd:startIndex:count is curently not available in windows."
+
+ pos := self position.
+ numberOfBytesOrNil isNil ifTrue:[
+ n := self size - pos.
+ ] ifFalse:[
+ n := numberOfBytesOrNil.
+ ].
+ nWritten := OperatingSystem
+ copyFromFd:self fileHandle
+ toFd:outStream fileHandle
+ startIndex:pos
+ count:n.
+ nWritten > 0 ifTrue:[
+ self position:pos+nWritten.
+ ].
+ nWritten = n ifTrue:[
+ ^ self
+ ].
+ ].
+
+ "fall back..."
+ ^ super copy:numberOfBytesOrNil into:outStream bufferSize:bufferSize.
"
|in out|
- in := 'Makefile' asFilename readStream.
- out := Stdout.
+ in := 'Make.proto' asFilename readStream.
+ in copyToEndInto:Stdout.
+ in close.
+
+ |in out|
+
+ in := 'Make.proto' asFilename readStream.
+ out := '/tmp/test' asFilename writeStream.
in copyToEndInto:out.
- in close.
+ in close. out close.
+ '/tmp/test' asFilename contents.
"
-!
-
-copyToEndInto:outStream
- "copy the data into another stream."
-
- ^ self copyToEndInto:outStream bufferSize:(self class bufferSizeForBulkFileCopy)
-
- "
- |in out|
-
- in := 'Makefile' asFilename readStream.
- out := Stdout.
- in copyToEndInto:out.
- in close.
- "
+
+ "Created: / 13-03-2019 / 16:27:04 / Stefan Vogel"
!
ioctl:ioctlNumber
@@ -3722,102 +3744,102 @@
|| (__INST(handleType) == @symbol(socketFilePointer))
|| (__INST(handleType) == @symbol(socketHandle))
|| (__INST(handleType) == @symbol(pipeFilePointer))) {
- if (((fp = __INST(handle)) != nil)
- && (__INST(mode) != @symbol(writeonly))
- && __bothSmallInteger(count, start)
- ) {
- f = __FILEVal(fp);
-
- cnt = __intVal(count);
- offs = __intVal(start) - 1;
-
- if (__isExternalBytesLike(anObject)) {
- OBJ sz;
-
- nInstBytes = 0;
- extPtr = (char *)(__externalBytesAddress(anObject));
- if (extPtr == NULL) goto bad;
- sz = __externalBytesSize(anObject);
- if (__isSmallInteger(sz)) {
- objSize = __intVal(sz);
- } else {
- objSize = 0; /* unknown */
- }
- } else {
- OBJ oClass = __Class(anObject);
- int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-
- nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
-
- switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
- case BYTEARRAY:
- case WORDARRAY:
- case LONGARRAY:
- case SWORDARRAY:
- case SLONGARRAY:
- case FLOATARRAY:
- break;
- case DOUBLEARRAY:
+ if (((fp = __INST(handle)) != nil)
+ && (__INST(mode) != @symbol(writeonly))
+ && __bothSmallInteger(count, start)
+ ) {
+ f = __FILEVal(fp);
+
+ cnt = __intVal(count);
+ offs = __intVal(start) - 1;
+
+ if (__isExternalBytesLike(anObject)) {
+ OBJ sz;
+
+ nInstBytes = 0;
+ extPtr = (char *)(__externalBytesAddress(anObject));
+ if (extPtr == NULL) goto bad;
+ sz = __externalBytesSize(anObject);
+ if (__isSmallInteger(sz)) {
+ objSize = __intVal(sz);
+ } else {
+ objSize = 0; /* unknown */
+ }
+ } else {
+ OBJ oClass = __Class(anObject);
+ int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+
+ nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
+
+ switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+ case BYTEARRAY:
+ case WORDARRAY:
+ case LONGARRAY:
+ case SWORDARRAY:
+ case SLONGARRAY:
+ case FLOATARRAY:
+ break;
+ case DOUBLEARRAY:
#ifdef __NEED_DOUBLE_ALIGN
- nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
+ nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
#endif
- break;
- case LONGLONGARRAY:
- case SLONGLONGARRAY:
+ break;
+ case LONGLONGARRAY:
+ case SLONGLONGARRAY:
#ifdef __NEED_LONGLONG_ALIGN
- nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
+ nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
#endif
- break;
- default:
- goto bad;
- }
- extPtr = (char *)0;
- objSize = __Size(anObject) - nInstBytes;
- }
-
- if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
- _buffered = (__INST(buffered) == true);
- if (_buffered) {
- __READING__(f);
- }
-
- if (extPtr) {
- __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
- } else {
- /*
- * on interrupt, anObject may be moved to another location.
- * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__,
- * to get a new address.
- */
- offs += nInstBytes;
- __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
- }
- /* 0 is NOT an EOF condition here ... */
- if (ret >= 0) {
- if (__isSmallInteger(__INST(position))) {
- INT np = __intVal(__INST(position)) + ret;
- OBJ t;
-
- t = __MKINT(np); __INST(position) = t; __STORE(self, t);
- } else {
- __INST(position) = nil; /* i.e. do not know */
- }
- RETURN (__mkSmallInteger(ret));
- }
- __INST(position) = nil;
+ break;
+ default:
+ goto bad;
+ }
+ extPtr = (char *)0;
+ objSize = __Size(anObject) - nInstBytes;
+ }
+
+ if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
+ _buffered = (__INST(buffered) == true);
+ if (_buffered) {
+ __READING__(f);
+ }
+
+ if (extPtr) {
+ __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
+ } else {
+ /*
+ * on interrupt, anObject may be moved to another location.
+ * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__,
+ * to get a new address.
+ */
+ offs += nInstBytes;
+ __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
+ }
+ /* 0 is NOT an EOF condition here ... */
+ if (ret >= 0) {
+ if (__isSmallInteger(__INST(position))) {
+ INT np = __intVal(__INST(position)) + ret;
+ OBJ t;
+
+ t = __MKINT(np); __INST(position) = t; __STORE(self, t);
+ } else {
+ __INST(position) = nil; /* i.e. do not know */
+ }
+ RETURN (__mkSmallInteger(ret));
+ }
+ __INST(position) = nil;
# ifdef __win32__
- __threadErrno = __WIN32_ERR(GetLastError());
+ __threadErrno = __WIN32_ERR(GetLastError());
# endif
- error = __mkSmallInteger(__threadErrno);
- }
- }
+ error = __mkSmallInteger(__threadErrno);
+ }
+ }
}
bad: ;
%}.
hitEOF ifTrue:[^ 0].
error notNil ifTrue:[
- lastErrorNumber := error.
- ^ self readError:error
+ lastErrorNumber := error.
+ ^ self readError:error
].
handle isNil ifTrue:[^ self errorNotOpen].
(mode == #writeonly) ifTrue:[^ self errorWriteOnly].
@@ -3826,7 +3848,7 @@
"
^ self primitiveFailed
- "Modified: / 22-11-2018 / 14:44:51 / Stefan Vogel"
+ "Modified: / 13-03-2019 / 17:07:07 / Stefan Vogel"
!
nextByte