This chapter describes changes and new features important for programmers using GemStone Smalltalk, including:
Changes in Class and Method handling
Socket Enhancements and new features
Changes in Errors and Error Handling
Starting in v3.1, changing class variables did not require creating a new version of the class in the case of a class with only a single version. However, if multiple versions of the class existed, a new version was required when class variables were changed.
This restriction for multiple-versioned classes has been lifted.
The following method has been added:
Behavior >> classVarAt: aClassVar otherwise: defaultValue
In previous releases, the class histories for the various String and Symbol classes included the single and multiple byte variants, e.g., String’s classHistory included both DoubleByteString and MultiByteString. This was designed for the historical constraints, migration, and support for isKindOf: and similar operations.
As of 3.4, class histories conform to the new rule:
At most one entry in any class history shall have (Globals at: entry name) == entry
The various String classes now have a classHistory size of 1.
isKindOf: and similar methods have been reimplemented to avoid any change in behavior.
The method Object >> changeClassTo: can be used to change the class of an object, including between classes with different numbers of named or indexed instance variables (indexed or varying instance variables are collection elements).
Previously, there was some undesirable behaviors in the cases when the number of and types of variables did not match:
The previous behavior is available using Object >> legacyChangeClassTo:.
changeClassTo: now behaves according to the following rules:
GsNMethod now implements printOn:. As a result, displaying a GsNMethod now includes the class and selector of the method.
A pragma is a literal selector or keyword message pattern that occurs between angle brackets at the start of a method after any temporaries. For example:
<foo: 123 >
<foo: 5 bar: 'update'>
<bar>
Pragma keywords follow method selector syntax, but they are symbol literals within the method, not message sends. Pragmas are useful to provide metadata about methods and to support keyword searching.
While primitive directives in GemStone look like pragmas, they are not; and primitive: is a reserved word in the first pragma in a method.
Some pragma support was introduced for seaside-based environments in v2.x, but the implementation was incomplete and not usable in the base GemStone environment. (#43541).
The Pragma class provides a way to find out information about pragmas. An instance of Pragma references the method that defines it, and the keyword and argument or arguments.
Sending GsNMethod >> pragmas will return an array of instances of Pragma.
Pragma class methods provide search capabilities. Pragma >> allNamed:in: returns a collection of all Pragmas with the given keyword in methods in the given class.
The following method has been added:
ClassOrganizer >> subhierarchyReport:includeOops:
topaz 1> run
ClassOrganizer new subhierarchyReport: PositionableStream
includeOops: true
%
PositionableStream 19773697 ( collection position readLimit)
ReadStream 19774721
WriteStream 19775745 ( writeLimit)
CypressMessageDigestStream 20292865
ReadWriteStream 19776769
FileStream 19777793 ( gsfile streamType)
GemStone includes the ability to differentiate multiple execution environments, primarily with the intention to allow support for Ruby. These are distinguished using the envId: argument. GemStone Smalltalk execution uses environment 0.
In v3.4, some methods have been added to increase operability in environments 1 and above, although this is not fully supported for general use. Image methods with ruby-specific names have been removed.
This is a new class, a subclass of nil (i.e., it does not inherit from Object). This is an abstract superclass for internal, hidden classes such as LargeObjectNode and NscNode.
Instance of subclasses of PrivateObject are normally for internal use only, but may be returned from some methods, such as reference path code. Only messages implemented in PrivateObject can be sent to instance of subclass of PrivateObject; other messages will signal a MessageNotUnderstood.
While usually collect:, select:, reject:, and similar methods return instances of the same kind of collection as the receiver, in some cases this is not correct. These overrides are normally handled by class-specific implementations of species, speciesForCollect, and speciesForSelect. In v3.4, the implementations have been cleaned up to move behavior into species* methods and remove unnecessary duplicates.
In addition, some RC classes incorrectly returned a result in an RC collection, rather than the equivalent non-RC collection, based on the return from speciesForCollect. (#46870)
The classes RcArray, RcIdentitySet, GsPipe, and RcPipe have been added.
RcIdentityBag has been reimplemented to be more efficient, with the name RcLowMaintenanceIdentityBag; both classes are available.
The class RcArray is similar to Array, but no conflict occurs when multiple users add objects to an RcArray using specific methods. If a conflict with other update operations on the RcArray occur, the add is replayed so that the commit can succeed.
Only the following methods support concurrent updates
add:
addAll:
at:put: (where no other session affects the element at the at: index)
size: (when size is increased)
RcLowMaintenanceIdentityBag is a reimplementation of RcIdentityBag that avoids the use of per-session add and remove sets. This avoids the periodic manual maintenance that is required in some cases for RcIdentityBag. Like RcIdentityBag, there is no commit conflict with multiple sessions adding and a single session removing objects.
While the API is similar, the performance characteristics will vary between RcIdentityBag and RcLowMaintenanceIdentityBag. As for v3.4, both classes exist. In a future release, it is expected that RcIdentityBag will be replaced by RcLowMaintenanceIdentityBag, and the current implementation be renamed.
Due to the implementation, while you can create indexes on an instance of RcLowMaintenanceIdentityBag, in this release only indexes of type btreePlusIndex are supported, not legacyIndexes. See Indexes on new Reduced-conflict classes.
For completeness with the other reduced-conflict classes, RcIdentitySet has been added. This provides an interface similar to Set, but using replay to handle commit conflicts. There is no commit conflict with multiple sessions adding and a single session removing objects.
Due to the implementation, while you can create indexes on an instance of RcIdentitySet, in this release only indexes of type btreePlusIndex are supported, not legacyIndexes. See Indexes on new Reduced-conflict classes.
The class GsPipe implements a first-in-first-out queue, with no conflict when a single session adds objects to the GsPipe, and only one session removes objects.
Internally, the GsPipe is implemented as a linked list of GsPipeElements. So, while most RC classes provide the reduced-conflict via either replaying conflicting transactions, or via per-session subcollections, GsPipe inherently has no conflict between operations at either end of the list.
The class RcPipe implements a first-in-first-out queue, with no conflict when multiple sessions add objects to the RcPipe, and only one session removes objects.
Internally, the RcPipe is implemented as a linked list of GsPipeElements. Unlike with GsPipe, if a conflict with an add by another session occurs, the add operation is replayed so that the commit can succeed. Only add: and operations that invoke add: are reduced-conflict.
Reduce-conflict classes use replay to resolve conflicts. Previously, all RC replay was serialized using a single lock, referenced by the global variable GemStoneRCLock.
Now, the Stone manages serialization so that only RC replays that conflict are serialized.
The global GemStoneRCLock has been removed, and the method System class >> waitForRcWriteLock:, which was intended for internal use in RC locking, has been removed.
The cache statistic RcRetryQueueSize is replaced by RcTransQueueSize.
ANSI specifies that add: and remove: should return the argument, not the receiver; there were a small number of GemStone collection classes that did not respect this.
ANSI does not specify a return type for addAll: or removeAll:; most GemStone collection classes return the receiver for these cases.
The following methods have been updated in v3.4 to return the argument, not the receiver.
ExceptionSet >> add:
RcIdentityBag >> remove:
RcIdentityBag >> remove:ifAbsent:
Bag >> removeAll:
RcIdentityBag >> removeAll:
Set >> removeAll:
You should review your application code to ensure that any uses of the return value from these methods are updated.
Set and Bag now implement intersection (*), union (+), and difference (-) operations. Previously these were only available in IdentityBag and its subclasses.
The following instance method has been added to SequencableCollection:
indexOfSubCollection: aSubColl
Returns the index of the first element of the receiver where that element and the subsequent ones are equal to those in aSubColl. The search is begun in the receiver starting at 1.
The following classes provide optimized behavior for using Streams to assemble text.
AppendStream is a kind of Stream that is only for append, that is, performing writes at the end, and later retrieving the entire contents by sending contents. It is not "positionable", and implements only a limited set of Stream protocol. This allows it to be significantly faster for some common use cases, such as using a stream to compose complex text.
AppendableString is a kind of String that understands AppendStream protocol as well as String protocol. This allows use of Stream protocol without redirection through a stream, and may provide performance benefits for some uses.
While non-stream methods are inherited from String and not disallowed, they are not intended to be used.
The PortableStream hierarchy contains useful methods that were not previously available in the LegacyStream classes. The following methods have been added:
WriteStreamLegacy >> crlf
WriteStreamLegacy >> crtab
WriteStreamLegacy >> crtab:.
WriteStreamLegacy >> space:
WriteStreamLegacy >> tab:
ReadStreamLegacy >> nextMatchFor:
The following methods have been added for performance:
String >> addAllUtf8: aCharacterOrString
Utf8 >> addAllUtf8: aCharacterOrString
Append the UTF8 encoding of the argument to the receiver.
CharacterCollection >> addCodePoint: aSmallInteger
DoubleByteString >> addCodePoint: aSmallInteger
String >> addCodePoint: aSmallInteger
Unicode16 >> addCodePoint: aSmallInteger
Unicode7 >> addCodePoint: aSmallInteger
Append the character with the given codePoint to the receiver.
This is implemented a primitive for String, DoubleByteString, Unicode 7 and Unicode 16.
The following methods have been added:
String >> encodeAsUTF8IntoString
DoubleByteString >> encodeAsUTF8IntoString
QuadByteString >> encodeAsUTF8IntoString
Previously there were private methods _encodeAsUTF8intoString, with the same behavior (note the capitalization changein i, as well as the underscore). These underscore versions remain for compatibility.
Previously, expressions such as these:
#(a + b) #(a - 3b)
interpreted the binary operator and variables in various ways, or errored.
Per ANSI, this is illegal syntax, and are now disallowed. Now, only legal identifiers or keywords can omit the leading #. Legal binary selector symbols must include #, and creating other symbols requires both # and quotes.
For example, assuming the intention is to create three-element arrays, to create the equivalents of the above expressions now requires:
#(a #+ b)
#(a #- #'3b')
While this example is in a literal Array, the change involves all cases of symbol parsing.
Note that with this change, GemStone still does not conform entirely to ANSI, which would require a leading # for keywords (which have a final colon). Expressions such as #(a: 3) retain the same, non-ANSI behavior.
Symbol >> keywords parses the receiver by $:, returning an Array of the selector keywords with each substring including the trailing $:. Previously, this had a number of shortcomings.
CharacterCollection >> isKeyword continues to use a more precise ANSI definition of keyword, and only returns true for legal keyword selectors, not for unary or binary selectors. This also now detects some cases of illegal secondary keywords that previously did not return false. (#46696)
The code that supports querying and indexing has been intensively reviewed and some parts have been reimplemented, and extensive testing has been added. Many bugs have been fixed, particularly in corner cases and in enumerated and set-valued indexes.
In v3.2, GemStone added a new indexing API the GsIndex/GsQuery API, to allow expansion on the historic API that uses UnorderedCollection methods and selectBlocks. Both APIs produce the same results, but many new features are not accessible from the historic API.
With v3.4, GemStone adds a new indexing internal structure, the BtreePlus index, based on a Btree+ implementation, to improve on the Legacy index internal structures based on simple Btrees and the RcIndexDictionary. Both internal implementations are available and (of course) produce exactly the same query results, but have different performance profiles and differences in default and error behavior.
Your application may use both the GsIndex/GsQuery API and the traditional API, and include both BtreePlus and Legacy internal structures. However, you cannot use both BtreePlus and Legacy indexing structures when creating multiple indexes on the same collection.
The data structures that supported indexing in previous releases included two data structures: Btrees, which contain the mappings for equality and allow range queries, and an RcIndexDictionary, which was used for mappings for identity queries and to map from the last element in the Btree node to the object itself.
v3.4 includes a new implementation of indexing data structures, the BtreePlus index. This btree+ based internal data structure includes the mappings that were previously done in the RcIndexDictionary, so no dictionary is needed.
The legacy indexing structures that were provided in previous releases are still available, and are the default for upgraded applications.
Using a BtreePlus indexes or a legacy index provides the same query results, but there are some differences in performance profiles and in default and error behavior. BtreePlus indexes perform best in combination with the new option optimizedComparisons, but there are more restrictions on the specific mixes of data types when optimizedComparisons are specified.
Optimized comparisons is a new feature that is key to achieving the performance benefits of BtreePlus indexes.
Historically, equality indexes may have lastElementClass objects that are of different classes but which can be ordered against each other, such as Strings and Symbols, Floats and NaNs, or any object and nil. However, while less-than and greater-than queries are not a problem, these objects may never be equal; for example, both ('aa' <= #aa) and ('aa' >= #aa) are true, but ('aa' = #aa) is not true. To support these cases, extra message sends are done for equality indexes (the issue, obviously, does not arise for identity indexes).
To avoid the extra comparison costs when basic comparisons (e.g. =) are sufficient, you may now specify the index option #optimizedComparisons.
optimizedComparisons only apply to btreePlusIndexes, not legacyIndexes.
To use the optimizedComparison option, the values must be a kind of the last element class. Nil is not allowed as a last element class value, and the following rules apply:
When specifying optimizedComparison for the index, you will get an error if an element in the collection does not follow these rules; for example, if any element in the collection has a nil in the instance variable that the index specifies. If your collection legally may include nils in indexed instance variables, or if you mix Strings and Symbols, you cannot use the optimizedComparison option, and using legacy Indexes is likely to provide better performance.
Note that nils along the path, or missing instance variables as allowed by the existing GsIndexOptions optionalPathTerms setting, are unaffected by optimizedComparison. optimizedComparison specifies what is in the btreePlus holding the last element class values, while nils along the path affect other lookup structures.
With legacy indexes, a lastElementClass of CharacterCollection, String, or Symbol (or the multi-byte equivalents) created indexes that allowed values of any of the above to be used as an indexed value. Specifying a lastElementClass of Unicode7, 16, or 32 created a unicode index with a collator; and in Unicode Comparison Mode, Unicode strings could be mixed with Traditional strings and symbols as indexed values. This behavior is the same for legacy indexes in v3.4.
However, using btreePlusIndex and optimizedComparison, mixing strings and symbols is disallowed. When using optimizedComparison, the meanings of the lastElementClass specification does distinguish between the "flavor" of the string.
When optimizedComparison is specified (either explicitly, or set as default), then:
The use of CharacterCollection is not recommended.
The following added convenience methods create an btreePlusIndex with optimizedComparison, regardless of any GsIndexOptions defaults, and restrict the lastElementClass values to the specified "flavor" of String:
stringOptimizedIndex:
stringOptimizedIndex:options:
symbolOptimizedIndex:
symbolOptimizedIndex:options:
symbolOptimizedIndex:collator:
symbolOptimizedIndex:collator:options:
unicodeStringOptimizedIndex:
unicodeStringOptimizedIndex:options:
unicodeStringOptimizedIndex:collator:
unicodeStringOptimizedIndex:collator:options:
btreePlusIndex and optimizedComparison are designed to significantly improve the performance of indexed queries, at the expense of somewhat less performant index updates. The performance improvements from these new indexed will depend on the performance profile of your application.
If the performance of indexed queries in your application is satisfactory, there is no need to change; the performance profile of legacyIndex is the same in v3.4, and overall performance is likely to be improved by other changes in v3.4.
If you are having issues with query performance, we recommend experimenting with the btreePlusIndexes and optimizedComparison, and verifying the performance benefits and ensuring that update performance does not create separate problems.
Note that btreePlusIndex without optimizedComparison is likely to be less performant than legacyIndexes.
The instance of GsIndexOptions associated with every index has additional importance in this release, since it controls the use of btreePlusIndex or legacyIndex. One or the other of these options must always be set. In addition, optimizedComparison can only apply when btreePlusIndex is set, and is strongly recommended to get the performance improvements of the btreePlusIndex.
The way the defaults for GsIndexOptions are handled has been changed to provide more levels of control between the three basic types (legacyIndex, btreePlusIndex with optimizedComparison, and btreePlusIndex without optimizedComparison). The defaults also support the other options available in previous releases.
Given the multiple levels of default, the way instances are combined has been updated to support intuitively mathematical operators of +, -, and the new not operator.
Internally, GsIndexOptions has fields for each option that may be nil, true, or false. When instances are combined, the option fields that are true or false in the second operand take precedence.
When using default, the order of precedence is:
The not operator has been introduced to improve clarity in specifying options.
For example, if the default is:
(GsIndexOptions btreePlusIndex + GsIndexOptions optimizedComparison)
Since optimizedComparison is only valid for btreePlusIndexes, when a GsIndexOptions is set to legacyIndex (or btreePlusIndex not), then optimizedComparison is automatically turned off.
The initial default for upgraded applications is:
The initial default for new repositories is:
(GsIndexOptions btreePlusIndex + GsIndexOptions optimizedComparison)
Each instance of GsIndexOption is based on this default. So, for example, for a new repository, creating an instance of reducedConflict using the expression:
(GsIndexOptions reducedConflict)
the resulting GsIndexOptions instance would be:
(GsIndexOptions btreePlusIndex + GsIndexOptions optimizedComparison + GsIndexOptions reducedConflict
To avoid the default, you may explicitly specify the state for each option. This is easily done using the not operator.
You can change the initial default by executing either of the following:
GsIndexOptions default: aGsIndexOptions
Persistently change the default GsIndexOptions for all users. This method can only be executed by SystemUser.
GsIndexOptions sessionDefault: aGsIndexOptions
Set the default GsIndexOptions for this session only.
For example, if your initial default is:
(GsIndexOptions btreePlusIndex + GsIndexOptions optimizedComparison)
(GsIndexOptions optimizedComparison not + GsIndexOptions reducedConflict)
will result in GsIndexOptions instances being created by default as:
(GsIndexOptions btreePlusIndex + GsIndexOptions reducedConflict)
The btreePlusIndex stays the same, the optimizedComparison is removed, and the reducedConflict is added.
This release introduced several new Reduced-Conflict (RC) classes, including two UnorderedCollection subclasses, RcIdentitySet and RcLowMaintenanceIdentityBag. In this release, you can create btreePlusIndexes on these classes, but you may not create legacyIndexes. This is due to the way conflict resolution is implemented in the new classes.
It is now allowed to use instances of GsQuery to search over collections that do not support indexes, such as Array. Performance will be comparable to iterative search, but it allows managing queries similarly over various collection types and using the GsQuery syntax to flexibly build queries.
Most, but not all, of the collection classes may be queried using GsQuery. Class methods have been added to indicate if GsQueries are allowed:
_canCreateQueryOnInstances
While the new substructure was developed and new features implemented, extensive additional testing has been added, and a large number of issues have been fixed; particularly relating to streamed queries, enumerated and set-value queries and queries involving nil values. These are not individually described here.
The SO_REUSEPORT socket option permits multiple AF_INET or AF_INET6 sockets to be bound to an identical socket address. This option may not be available on all OS revisions.
The class GsSignalingSocket has been added, a subclass of GsSocket. This class signals kinds of Error, rather than returning nil, when a socket operation fails.
GsSecureSocket is now a subclass of GsSignalingSocket.
Now when using GsSecureSocket, when an error occurs, the methods signal a SocketError or SecureSocketError rather than returning false.
This is true for most but not all error conditions; in particular, methods that return true or false, such as GsSecureSocket >> readWillNotBlock, will return nil on error.
SSLv3 connections are no longer supported, as they are known to be insecure; only TLSv1 connections are currently supported.
GsSecureSocket server sockets now support the verification modes SSL_VERIFY_FAIL_IF_NO_PEER_CERT and SSL_VERIFY_CLIENT_ONCE, which can be used when server certificate verification is enabled.
New methods in the image allow you to set options to an array that may include:
These options are only supported for server sockets; there are no verification options for client sockets.
The following methods have been added
GsSecureSocket class >> fetchCertificateVerificationOptionsForServer
Answers an Array of Symbols which represent the certificate verification options that can be used by server sockets.
GsSecureSocket class >> setCertificateVerificationOptionsForServer: anArray
Sets the certificate verification options for server sockets using an Array of Symbols. If anArray is empty then any previously set options are cleared. Certificate verification for server sockets must be enabled before executing this method. Only applies for sockets created after this method is executed.
GsSecureSocket >> fetchCertificateVerificationOptions
Answers an Array of Symbols which represent the certificate verification options that can be used by the receiver. Certificate verification options are only supported by server sockets.
GsSecureSocket >> setCertificateVerificationOptions: anArray
Sets the certificate verification options for the receiver, which must be a server socket, using an Array of Symbols. If anArray is empty then any previously set options are cleared. The receiver must enable certificate verification before this method is executed, and must use this method before the receiver attempts a connection with its peer.
The following are added protocol to check for the current status of verification:
GsSecureSocket class >> certificateVerificationEnabledOnClient
Answer true if certificate verification is enabled for client sockets.
GsSecureSocket class >> certificateVerificationEnabledOnServer
Answer true if certificate verification is enabled for server sockets.
GsSecureSocket >> certificateVerificationEnabled
Answer true if certificate verification is enabled on the receiver.
Methods have also been added to specify a certificate directory.
GsSecureSocket class >> useCACertificateDirectoryForClients: aDirectoryString
Specifies a directory where trusted certificate authority (CA) certificates in PEM format are located. The certificates in this directory will be used to authenticate certificates provided by servers during the SSL handshake. The directory may contain more than one certificate.
Certificates are loaded into the internal SSL state which is valid for the current session only; the SSL state is not committed to the repository. Has no effect on instances created before the method was called, nor on server sockets.
If successful, this method also enables certificate verification for client sockets as if the #enableCertificateVerificationOnClient method was called.
GsSecureSocket class >> useCACertificateDirectoryForServers: aDirectoryString
Specifies a directory where trusted certificate authority (CA) certificates in PEM format are located. The certificates in this directory will be used to authenticate certificates provided by client during the SSL handshake. The directory may contain more than one certificate.
Certificates are loaded into the internal SSL state which is valid for the current session only; the SSL state is not committed to the repository. Has no effect on instances created before the method was called, nor on client sockets.
If successful, this method also enables certificate verification for server sockets as if the #enableCertificateVerificationOnServer method was called.
The class SecureSocketError has been added, and is used for security errors signaled from GsSecureSocket.
SocketError asString has been added, providing a printed version that is specific to SocketError.
The Random class is an abstract class, with actual random numbers generated by subclasses HostRandom, Lag1MwcRandom, and Lag25000CmwcRandom.
In previous releases, Random class methods new and seed: returned instances of Lag25000CmwcRandom. This implementation of random number generator took significant time to create initially, and was designed to be used where a series of reliably random numbers was needed. The large overhead of creation, however, made it unsuitable for cases in which a single random number was required, and a truly random number was not required. (#46990)
This has been changed in v3.4. Now, Random new will return an instance of HostRandom, and Random seed: returns an instance of Lag1MwcRandom.
For applications that have strict requirements for randomness, it is recommended to refer to the specific class directly, e.g. Lag25000CmwcRandom seed: .
For compliance with the IEEE 754 spec on floating point exceptions, starting with GemStone v3.0, certain floating point operations that signalled exceptions in v2.x instead returned an exception float, such as a NaN or Infinity. For example, dividing by 0.0 returned PlusInfinity rather than erroring. This can create potentially serious problems for applications that rely on exceptions to detect errors. (#46398)
Now, you may configure GemStone such that floating point operations that by default return the IEEE 754-specified ExceptionalFloat will instead signal an Exception.
The following are the symbols representing the kinds of errors for which exception signalling can be enabled:
To configure the set of errors for which Exceptions are signalled, use class protocol for FloatingPointError.
enableAllExceptions
Enable exceptions for all kinds of errors
enabledExceptions
Return an Array containing zero or more of the error symbols, reflecting the most recent call to #enableAllExceptions or #enableExceptions:
enableExceptions: symOrArrayOfSym
The argument may be one of the error symbols, or an Array containing zero or more of these Symbols , or nil. After an arithmetic operation when an exception occurs, it will check and if the corresponding symbol is enabled, it will signal a FloatingPointError, otherwise it will return the ExceptionalFloat.
Use care when enabling all exceptions, in particular enabling #inexactResults, as this may impact your application unexpectedly. When #inexactResults is enabled, expressions such as 1.0 / 3 will error.
Some non-floating point operations also use FloatingPointError, such as LargeInteger overflow. These exceptions are signaled regardless of FloatingPointError status, since there is no appropriate kind of number to return.
In addition to this way of controlling exceptions, several other methods have been added:
Number, Float >> roundedNoFpe
Returns the Integer nearest in value to the receiver, ignoring any #inexactResult that might be enabled in FloatingPointError
Number, Float >> truncatedNoFpe
Returns the integer that is closest to the receiver, on the same side of the receiver as zero is located. ignoring any #inexactResult that might be enabled in FloatingPointError
Float >> noInexactResultDo: aBlock
Return value of executing aBlock, suppressing any FloatingPointError for #inexactResult that might occur.
For numbers that are not specials, such as LargeIntegers, Fractions, and ScaledDecimals, some code paths could return an instance that was not invariant. (#46790). This does not apply to specials/immediate: SmallInteger, SmallDouble, and SmallFraction.
Now, all numbers are return as invariant.
#postCopy methods have been added to the non-special classes.
The following methods on BinaryFloat class have been replaced by the new FloatingPointException handling. While these methods are technically only deprecated in this release, they are no longer functional; you should update any references to these methods in your code as part of the upgrade to 3.4.
GsEventLog is a shared, reduced-conflict logging tool that allows multiple sessions to:
A GsEventLog class variable holds a instance of GsEventLog, which in turn holds a collection of log entries, which are instances of kinds of GsEventLogEntry. It is allowed for user applications to create custom subclasses of GsEventLogEntry.
Each event has a priority. Built in priorities are fatal, error, warning, info, debug, and trace; these are stored internally as integers.
The entries are stored in an instance of RcArray, allowing concurrent writes of log entries. Note that the order of elements is based on the order in which the commits occurred, while entry timestamps reflect the time at which the entry was created.
GsEventLog may hold both application (user) events and system events. User entries can be added in two ways: class convenience methods such as logError:, logInfo:, etc., or by creating an instance of GsEventLogEntry and sending addToLog. A commit is required to make the log entry persistent.
System events should be added only by GemStone code. In this release, GemStone code does not write System events.
To create a string containing text representation of the entire contents, send
GsEventLog current report
To search for a subset of entries with particular attributes
(GsEventLog current entriesSatisfying: aBlock) report
GsEventLog is not reduced conflict for delete. It is recommended to lock the log using GsEventLog >> acquireGsEventLogLock. The lock is cleared automatically on commit.
You can clear all events using the following method:
GsEventLog current deleteAllEntries.
By querying for specific methods, you can delete those methods using deleteEntry: or deleteEntries:
It is possible to restrict modifying or removing events. To do this, execute
GsEventLog entriesUnmodifiable
After this is executed, new entries to the log are made invariant and the standard delete methods will not delete them. However, they are not protected from delete using private delete protocol.
System events are also protected from modification or deletion, other than using private delete protocol.
topaz 1> run
[GsEventLog logDebug: 'About to perform divide by zero'.
1 / 0.
GsEventLog logDebug: 'After divide by zero'.
true]
on: Error
do: [:ex | GsEventLog logObject: ex. ex resume].
%
true
topaz 1> run
GsEventLog current report
%
'2017-07-13 16:36:44.3820 24198 Trace About to perform divide by zero
2017-07-13 16:36:44.3821 24198 Trace a ZeroDivide occurred (error
2026), reason:numErrIntDivisionByZero, attempt to divide 1 by zero
a ZeroDivide occurred (error 2026), reason:numErrIntDivisionByZero,
attempt to divide 1 by zero
2017-07-13 16:36:44.3822 24198 Trace After divide by zero
The class Message has been added, for improved ANSI compatibility in handling does not understand. Previously, two-element arrays held the class and selector.
Now, doesNotUnderstand: is invoked with an instance of Message, and sending #message to MessageNotUnderstood error returns an instance of Message.
For compatibility, Message understands at:, size, and asArray, so existing code that expects a two-element array will continue to work correctly.
Previously error 2283, invoked as #rtErrInvalidArgClass, mapped to ArgumentError; now this maps to ArgumentTypeError.
Previously code that included statements with no effect triggered a compiler warning and so did not compile. (#42510)
Now, a warning is triggered in this case for method compilation. Do-its may ignore the warning.
The errors returned for invalid input to Unicode7 and Unicode16 at:put: arguments has changed. Previously these provided an OutOfRange error 2723 with an unclear message; now, they signal a ArgumentError 2004, or OffsetError 2003.
2518 #authErrStoreTrav /AUTH_ERR_STORE_TRAV
Smalltalk class: SecurityError
Error reported on an attempt to change the object security policy via store traversal.
2608 rtErrGroupAlreadyExists / RT_ERR_GROUP_ALREADY_EXISTS
Smalltalk class: ImproperOperation
Attempt to create a group when the group already exists.
2609 rtErrPrincipalAlreadyExists / RT_ERR_PRINCIPAL_ALREADY_EXISTS
Smalltalk class: ImproperOperation
Attempt to create a kerberos principal when the principal already exists
2755 rtErrGsSecureSocket / ERR_SecureSocketError
Smalltalk class: SecureSocketError (new in v3.4)
Certain security-related errors on a GsSecureSocket.
4016 #gsErrSslShutdown / GS_ERR_SSL_SHUTDOWN_ERR
Smalltalk class: SecureSocketError (new in v3.4)
Network error when switching from SSL to non SSL during login
4030 #errLostOtGci / ERR_LOST_OT_GCI
Smalltalk class: ImproperOperation
LostOt while waiting for a GCI command, and the transactionMode not transactionless
2080 rtErrCantChangeClass, Illegal attempt to change the class of an object.
This error now includes a third argument: the reason why the change was illegal .
The following errors are no longer defined:
2037 classErrConstraintNotClass
2062 rtErrCannotChgConstraint (still referenced in image)
2107 objErrConstraintViolation (still referenced in image)
2156 repErrReplicateNotMounted
2148 rtErrInvalidConstraintForMigration (was previously only referenced from image, now entirely removed)
2159 rtErrInvalidElementConstraintForMigration
2308 rtErrBagNoConstraintAlongPath
2320 rtErrBadConstraintForMigration
2327 rtErrLastConstraintNotBoolean
2340 objErrDictConstraintViolation (still referenced in image)
Previously, the class of the block was included, which cluttered the view.
For support for GCI application debugging, the following methods have been added:
GsProcess >> gciStepIntoFromLevel:
GsProcess >> gciStepOverFromLevel:
GsProcess >> gciStepThruFromLevel:
These replace the deprecated GCIStep() and GciStep_() GCI functions.
The lineLimit: keyword has been added to the most general form of stackReportToLimit*:
GsProcess >> stackReportToLevel:withArgsAndTemps:andMethods:includeSource:lineLimit:
Other stackReportToLevel* methods now use a default line size of 100.
Also, for the stackReportToLevel* methods that have the keyword includeSource:, this accepts an additional argument, #block, allowing display of the source for Executed Blocks.
Previously, the default interval was 1 millisecond (defaultIntervalNs returned 1000000). Now, it is 0.5 milliseconds (i.e. 500 microseconds); defaultIntervalNs returns 500000.
The way ProfMonitor and ProfMonitorTree generate reports has been changed to allow more control over the specific reports. New methods have been added to support this; existing methods return reports as in previous versions.
A number of private reporting methods have been removed, and the flow of control through class methods has been cleaned up.
Report headers now include the reporting threshold.
The following methods have been added:
ProfMonitor class >> monitorBlock:downTo:intervalNs:reports:
ProfMonitor class >> monitorBlock:reports:
ProfMonitor >> reportDownTo:reports:
These methods accept the additional keyword reports:, which allows you to specify an array of report symbols. These symbols are:
#samples - sample counts report is included in the resulting output.
#stackSamples - stack sampling report is included in the resulting output.
#senders - method senders report is included in the resulting output.
#objCreation - Enables object creation tracking; the object creation report is included in the resulting output.
#tree - causes ProfMonitorTree to be used for profiling, and the method execution tree report is included in the resulting output.
#objCreationTree- causes ProfMonitorTree to be used for profiling, and enabled object creation tracking; the object creation tree report is included in the resulting output.
It is now supported to save an instance of ProfMonitor and perform the analysis and report later.
In order to perform the analysis later, it is necessary that the underlying raw results file not be deleted. The convenience monitorBlock* methods that return reports delete the raw data file; so to allow later analysis, use the new method ProfMonitor >> runBlock:.
run
UserGlobals at: #aProfMon put:
(ProfMonitor runBlock: [
200 timesRepeat: [System myUserProfile dictionaryNames] ]).
%
commit
logout
login
run
aProfMon reportAfterRun
%
The private method _objectForOop: has been in use as a way to retrieve objects based on OOP. While "oop fishing" has risks, it is a useful tool for users who understand the issues and risks.
A public version, Object >> objectForOop:, has been added. This method differs from _objectForOop: in that it errors if no object with the given OOP exists. This avoids the ambiguity when resolving using nil’s OOP.
By default, DateAndTime now returns an instance with the seconds as a SmallDouble, allowing arbitrary resolution (to system limits). However, this produced more digits of resolution than was needed.
The following method has been added:
DateAndTime class >> nowWithScale: anInteger
Creates a DateAndTime for the current time, using a ScaledDecimal with the given scale as the subsecond resolution. For example, using a scale of 3 will produce millisecond resolution.
To allow application-wide configuration of DateAndTime scale with a particular scale, the following new method can be used:
DateAndTime class >> setDefaultScale: anInteger
If this is executed as SystemUser with anInteger 0<= n <= 30000, this value will be used by subsequent DateAndTime >> now method invocations to create a DateAndTime with that given ScaledDecimal scale. If this was not set, or is set to nil, the behavior is unchanged, and DateAndTime >> now returns an instance with SmallDouble seconds.
These operations now use vfork() instead of fork(), and are much faster; one test demonstrated a 40x performance improvement.
The class GsBitmap has been added, encapsulating behavior of GemStone’s hidden sets. While GsBitmap can be considered as a collection and implements Collection protocol, it does not inherit from Collection. Instances of GsBitmap cannot be committed, and you cannot add temporary objects nor specials to a GsBitmap.
GsBitmaps are most useful when doing repository analysis. See GsBitmap for more information on using GsBitmaps.
The following methods have been added:
TestSuite >> debug
TestCase >> debug
TestCase >> run
TestCase >> printString now produces the debug invocation of that case, as with GsTestCase.
Cypress is a dialect-independent solution for managing Smalltalk source code. FileTree is the GemStone version of this project.
A number of Cypress classes have been added. These are preliminary; future releases may make extensive changes to make internal use of these for code management.