scopeable_6650_patch_20220901a.patch
new/src/com/goldencode/p2j/main/StandardServer.java 2022-09-01 08:47:05 +0000 | ||
---|---|---|
196 | 196 |
** CA 20220405 Added authentication and authorization for web requests. When this is enabled, |
197 | 197 |
** the target API call will be executed under the authenticated FWD context, and not |
198 | 198 |
** the agent's context. |
199 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
200 |
** registration is now specific to each type of scopeable. For each case, the block |
|
201 |
** will be registered for scope support (for that particular scopeable) only when |
|
202 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
203 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
204 |
** processing all the scopeables for each and every block. |
|
199 | 205 |
*/ |
200 | 206 | |
201 | 207 |
/* |
... | ... | |
1166 | 1172 |
/** |
1167 | 1173 |
* Register default services: |
1168 | 1174 |
* <ol> |
1169 |
* <li> {@link SharedVariableManager} </li> |
|
1170 |
* <li> {@link UnnamedStreams} </li> |
|
1171 |
* <li> {@link LogicalTerminal} </li> |
|
1172 | 1175 |
* <li> {@link Persistence} </li> |
1173 |
* <li> {@link AccumulatorManager} </li> |
|
1174 | 1176 |
* <li> {@link WebServer} </li> |
1175 | 1177 |
* <li> custom account extension plugin </li> |
1176 | 1178 |
* </ol> |
... | ... | |
1237 | 1239 |
@Override |
1238 | 1240 |
public void initialize() |
1239 | 1241 |
{ |
1240 |
SharedVariableManager.initialize(); |
|
1241 |
} |
|
1242 |
}); |
|
1243 | ||
1244 |
serverHooks.add(new AbstractInitTermListener() |
|
1245 |
{ |
|
1246 |
@Override |
|
1247 |
public void initialize() |
|
1248 |
{ |
|
1249 |
UnnamedStreams.initialize(); |
|
1250 |
} |
|
1251 |
}); |
|
1252 |
|
|
1253 |
serverHooks.add(new AbstractInitTermListener() |
|
1254 |
{ |
|
1255 |
@Override |
|
1256 |
public void initialize() |
|
1257 |
{ |
|
1258 |
LogicalTerminal.initialize(); |
|
1259 |
} |
|
1260 |
}); |
|
1261 |
|
|
1262 |
serverHooks.add(new AbstractInitTermListener() |
|
1263 |
{ |
|
1264 |
@Override |
|
1265 |
public void initialize() |
|
1266 |
{ |
|
1267 | 1242 |
ServerKeyStore.initialize(); |
1268 | 1243 |
} |
1269 | 1244 |
}); |
... | ... | |
1309 | 1284 |
} |
1310 | 1285 |
} |
1311 | 1286 |
}); |
1312 |
|
|
1313 |
serverHooks.add(new AbstractInitTermListener() |
|
1314 |
{ |
|
1315 |
@Override |
|
1316 |
public void initialize() |
|
1317 |
{ |
|
1318 |
AccumulatorManager.initialize(); |
|
1319 |
} |
|
1320 |
}); |
|
1321 |
|
|
1287 | ||
1322 | 1288 |
// register controller for method execution tracing |
1323 | 1289 |
serverHooks.add(new AbstractInitTermListener() |
1324 | 1290 |
{ |
... | ... | |
1712 | 1678 |
false, |
1713 | 1679 |
false); |
1714 | 1680 |
|
1681 |
// make sure that the global block gets a special notification - but only for non-appserver sessions. |
|
1682 |
if (!AppServerManager.isRemote() && !TransactionManager._isHeadless()) |
|
1683 |
{ |
|
1684 |
Finalizable cleaner = new Finalizable() |
|
1685 |
{ |
|
1686 |
@Override |
|
1687 |
public void finished() |
|
1688 |
{ |
|
1689 |
LogicalTerminal.getInstance().pauseBeforeEnd(TransactionManager.isProcessingQuit()); |
|
1690 |
} |
|
1691 |
|
|
1692 |
@Override |
|
1693 |
public void iterate() |
|
1694 |
{ |
|
1695 |
// nothing to do here |
|
1696 |
} |
|
1697 |
|
|
1698 |
@Override |
|
1699 |
public void retry() |
|
1700 |
{ |
|
1701 |
// nothing to do here |
|
1702 |
} |
|
1703 |
|
|
1704 |
@Override |
|
1705 |
public void deleted() |
|
1706 |
{ |
|
1707 |
// nothing to do here |
|
1708 |
} |
|
1709 |
}; |
|
1710 |
|
|
1711 |
TransactionManager.registerFinalizable(cleaner, true); |
|
1712 |
} |
|
1713 |
|
|
1715 | 1714 |
Object result = null; |
1716 | 1715 |
try |
1717 | 1716 |
{ |
new/src/com/goldencode/p2j/persist/BufferManager.java 2022-09-01 08:47:17 +0000 | ||
---|---|---|
444 | 444 |
** were added to the collection during iterating it, resulting in a |
445 | 445 |
** ConcurrentModificationException (refs #6356). |
446 | 446 |
** CA 20220707 Cache the converted Java names for the dynamic buffers. |
447 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
448 |
** registration is now specific to each type of scopeable. For each case, the block |
|
449 |
** will be registered for scope support (for that particular scopeable) only when |
|
450 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
451 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
452 |
** processing all the scopeables for each and every block. |
|
447 | 453 |
*/ |
448 | 454 | |
449 | 455 |
/* |
... | ... | |
517 | 523 |
import com.goldencode.p2j.security.*; |
518 | 524 |
import com.goldencode.p2j.util.*; |
519 | 525 |
import com.goldencode.p2j.util.LogHelper; |
526 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
520 | 527 |
import com.goldencode.p2j.util.ErrorManager; |
521 | 528 |
import com.goldencode.util.*; |
529 |
import com.goldencode.util.Stack; |
|
522 | 530 | |
523 | 531 |
/** |
524 | 532 |
* Manages all record buffers within the current user context. This includes |
... | ... | |
568 | 576 |
@Override protected BufferManager initialValue() { return (new BufferManager()); } |
569 | 577 |
}; |
570 | 578 |
|
571 |
/** Flag indicating whether class was initialized, i.e. {@link #initialize} was called */ |
|
572 |
private static boolean initialized = false; |
|
573 |
|
|
574 | 579 |
/** A cache of buffer-related fields defined in a specific legacy-converted class. */ |
575 | 580 |
private static final Map<Class<?>, Set<Field>> classBufferFields = new ConcurrentHashMap<>(); |
576 | 581 |
|
... | ... | |
637 | 642 |
private final ScopedList<RecordBuffer> openBuffers = new ScopedList<>(); |
638 | 643 |
|
639 | 644 |
/** |
640 |
* The buffers touched via a Create, Update or Delete operation, in each scope. If the full transaction |
|
645 |
* The buffers touched via a Create, Update, Copy or Delete operation, in each scope. If the full transaction
|
|
641 | 646 |
* block is not {@link #commit committed} or {@link #rollback rolled back}, then the buffers will be merged |
642 | 647 |
* in the previous scope. |
643 | 648 |
*/ |
... | ... | |
662 | 667 |
private final ScopedDictionary<OutputTableHandleCopier, Integer> thOutputParameters = |
663 | 668 |
new ScopedDictionary<>(); |
664 | 669 |
|
670 |
/** Track the external scopes pushed on {@link BufferManager}. */ |
|
671 |
private final Stack<Boolean> externalScope = new Stack<>(); |
|
672 |
|
|
665 | 673 |
/** Database to transaction wrapper instance map */ |
666 | 674 |
private final Map<Database, TxWrapper> txWrapperMap = new HashMap<>(); |
667 | 675 |
|
... | ... | |
692 | 700 |
/** Transaction helper */ |
693 | 701 |
private final TransactionManager.TransactionHelper txHelper; |
694 | 702 |
|
703 |
/** Change broker instance. */ |
|
704 |
private final ChangeBroker changeBroker; |
|
705 |
|
|
695 | 706 |
/** Block depth at which full application transaction began, or -1 if not in a transaction */ |
696 | 707 |
private int transactionDepth = -1; |
697 | 708 |
|
... | ... | |
742 | 753 |
txHelper.registerStopVetoHandler(this); |
743 | 754 |
txHelper.registerResettable(this); |
744 | 755 |
|
756 |
changeBroker = ChangeBroker.get(); |
|
757 |
|
|
745 | 758 |
if (LOG.isLoggable(Level.FINE)) |
746 | 759 |
{ |
747 | 760 |
LOG.log(Level.FINE, "BufferManager created in context " + Utils.describeContext()); |
... | ... | |
749 | 762 |
} |
750 | 763 |
|
751 | 764 |
/** |
752 |
* Retrieve the context-local instance of this class, instantiating it |
|
753 |
* first if necessary. |
|
765 |
* Retrieve the context-local instance of this class, instantiating it first if necessary. |
|
754 | 766 |
* |
755 | 767 |
* @return Context-local instance of this class. |
756 |
* @throws IllegalStateException |
|
757 |
* when {@link BufferManager} is not activated, i.e. {@link |
|
758 |
* #initialize()} is not called. |
|
759 | 768 |
*/ |
760 | 769 |
public static BufferManager get() |
761 | 770 |
{ |
762 |
if (!BufferManager.initialized) |
|
763 |
{ |
|
764 |
throw new IllegalStateException( |
|
765 |
"An attempt to use uninitialized BufferManager. Is persistence activated?"); |
|
766 |
} |
|
767 |
|
|
768 | 771 |
BufferManager bm = context.get(); |
769 | 772 |
if (bm.connMgr == null) |
770 | 773 |
{ |
... | ... | |
783 | 786 |
} |
784 | 787 |
|
785 | 788 |
/** |
789 |
* Register the {@link BufferManager} instance as for scope notifications at the current block. |
|
790 |
* |
|
791 |
* @param bufferManager |
|
792 |
* The {@link BufferManager} instance. |
|
793 |
*/ |
|
794 |
public static void registerScopeable(BufferManager bufferManager) |
|
795 |
{ |
|
796 |
if (bufferManager == null) |
|
797 |
{ |
|
798 |
bufferManager = get(); |
|
799 |
} |
|
800 |
|
|
801 |
bufferManager.txHelper.registerBlockScopeable(bufferManager); |
|
802 |
bufferManager.txHelper.registerBlockScopeable(bufferManager.changeBroker); |
|
803 |
} |
|
804 | ||
805 |
/** |
|
806 |
* Register the {@link BufferManager} instance as pending scopeable, to be added to the next block. |
|
807 |
* |
|
808 |
* @param bufferManager |
|
809 |
* The {@link BufferManager} instance. |
|
810 |
*/ |
|
811 |
public static void registerPendingScopeable(BufferManager bufferManager) |
|
812 |
{ |
|
813 |
if (bufferManager == null) |
|
814 |
{ |
|
815 |
bufferManager = get(); |
|
816 |
} |
|
817 |
|
|
818 |
bufferManager.txHelper.registerPendingScopeable(bufferManager); |
|
819 |
bufferManager.txHelper.registerPendingScopeable(bufferManager.changeBroker); |
|
820 |
} |
|
821 |
|
|
822 |
/** |
|
786 | 823 |
* Cleanup of pending resources. This is called when the external procedure constructor failed |
787 | 824 |
* to build a new object because of an exception thrown in a member initialization (shared |
788 | 825 |
* frame/table). |
... | ... | |
796 | 833 |
} |
797 | 834 |
|
798 | 835 |
/** |
799 |
* Register with the {@link com.goldencode.p2j.util.TransactionManager |
|
800 |
* TransactionManager} a factory object which creates instances of this |
|
801 |
* class, so that they can be registered to receive notifications of |
|
802 |
* runtime scope start and finish events. |
|
803 |
* <p> |
|
804 |
* This method should be invoked once during the server bootstrap phase. |
|
805 |
*/ |
|
806 |
static void initialize() |
|
807 |
{ |
|
808 |
TransactionManager.registerScopeableFactory(BufferManager::get); |
|
809 |
BufferManager.initialized = true; |
|
810 |
} |
|
811 |
|
|
812 |
/** |
|
813 | 836 |
* Register this buffer as 'dirty' in the current scope. |
814 | 837 |
* <p> |
815 | 838 |
* This registration doesn't mean that at the time of {@link #commit}, {@link #rollback}, or |
... | ... | |
1045 | 1068 |
} |
1046 | 1069 |
|
1047 | 1070 |
/** |
1071 |
* Find the nearest external block (from the bottom of the stack). |
|
1072 |
* |
|
1073 |
* @return See above. |
|
1074 |
*/ |
|
1075 |
public int findNearestExternal() |
|
1076 |
{ |
|
1077 |
int idx = externalScope.size() - 1; |
|
1078 |
while (idx > 0) |
|
1079 |
{ |
|
1080 |
if (externalScope.get(idx)) |
|
1081 |
{ |
|
1082 |
return idx + 1; |
|
1083 |
} |
|
1084 |
|
|
1085 |
idx = idx - 1; |
|
1086 |
} |
|
1087 |
|
|
1088 |
return -1; |
|
1089 |
} |
|
1090 |
|
|
1091 |
/** |
|
1048 | 1092 |
* Check the specified exception and determine whether we want to allow it |
1049 | 1093 |
* to be honored by the {@link TransactionManager}, or whether we want to |
1050 | 1094 |
* veto the STOP at this scope. |
... | ... | |
1235 | 1279 |
thOutputParameters.addScope(null); |
1236 | 1280 |
undoData.addScope(null); |
1237 | 1281 |
fieldScopes.scopeStart(); |
1282 |
externalScope.push(txHelper.isExternalBlock()); |
|
1238 | 1283 |
|
1239 | 1284 |
BatchModeData crtBatchScope = batchModeStack.peek(); |
1240 | 1285 |
if (crtBatchScope != null && crtBatchScope.batchDepth == BatchModeData.INTERNAL) |
... | ... | |
1455 | 1500 |
fieldScopes.scopeFinished(); |
1456 | 1501 |
openStaticTempTables.deleteScope(); |
1457 | 1502 |
thOutputParameters.deleteScope(); |
1503 |
externalScope.pop(); |
|
1458 | 1504 |
BatchModeData bmd = batchModeStack.pop(); |
1459 | 1505 |
if (bmd.batchDepth == BatchModeData.INTERNAL) |
1460 | 1506 |
{ |
... | ... | |
1536 | 1582 |
} |
1537 | 1583 |
|
1538 | 1584 |
/** |
1585 |
* Get the {@link ScopeId} for the instance. |
|
1586 |
* |
|
1587 |
* @return {@link ScopeId#BUFFER_MANAGER}. |
|
1588 |
*/ |
|
1589 |
@Override |
|
1590 |
public ScopeId getScopeId() |
|
1591 |
{ |
|
1592 |
return ScopeId.BUFFER_MANAGER; |
|
1593 |
} |
|
1594 |
|
|
1595 |
/** |
|
1539 | 1596 |
* Provides a notification that a batch is starting or ending. Enters or |
1540 | 1597 |
* exits batch assignment mode for all record buffers in this context, |
1541 | 1598 |
* depending on the value of <code>start</code>. |
... | ... | |
1660 | 1717 |
* |
1661 | 1718 |
* @return {@code true} if we are in a transaction, else {@code false}. |
1662 | 1719 |
*/ |
1720 |
@Deprecated |
|
1663 | 1721 |
public boolean isTransactionAt(int level) |
1664 | 1722 |
{ |
1665 | 1723 |
return transactionDepth >= 0 && transactionDepth <= level; |
... | ... | |
1672 | 1730 |
* @return {@code true} if we are at (and within) a full transaction boundary, else {@code |
1673 | 1731 |
* false}. |
1674 | 1732 |
*/ |
1733 |
@Deprecated |
|
1675 | 1734 |
public boolean isFullTransaction() |
1676 | 1735 |
{ |
1736 |
// TODO: this has dependency on the full app stack |
|
1677 | 1737 |
return transactionDepth >= 0 && getOpenBufferScopes() - 1 == transactionDepth; |
1678 | 1738 |
} |
1679 | 1739 |
|
... | ... | |
1684 | 1744 |
* @return Zero-based block depth of current, full transaction, or -1 if we are not currently |
1685 | 1745 |
* within a transaction. |
1686 | 1746 |
*/ |
1747 |
@Deprecated |
|
1687 | 1748 |
public int getFullTransactionBlock() |
1688 | 1749 |
{ |
1689 | 1750 |
return transactionDepth; |
... | ... | |
2658 | 2719 |
*/ |
2659 | 2720 |
void openScopeAt(int openScopeDepth, RecordBuffer buffer) |
2660 | 2721 |
{ |
2722 |
// TODO: this seems to be called only for 'openScopeDepth == 0'. |
|
2723 |
|
|
2661 | 2724 |
if (buffer.isActive()) |
2662 | 2725 |
{ |
2663 | 2726 |
if (openScopeDepth == 0) |
... | ... | |
3147 | 3210 |
* @return {@code true} if the block is considered "important" by the above criteria, else |
3148 | 3211 |
* {@code false}. |
3149 | 3212 |
*/ |
3150 |
private boolean isImportantBlockTransition()
|
|
3213 |
public boolean isImportantBlockTransition()
|
|
3151 | 3214 |
{ |
3152 | 3215 |
return !txHelper.isTransaction() || |
3153 | 3216 |
txHelper.currentTransactionLevel() != TransactionManager.NO_TRANSACTION; |
... | ... | |
3158 | 3221 |
* primary key. One instance of this class holds all such objects for a |
3159 | 3222 |
* single buffer in a single scope. |
3160 | 3223 |
*/ |
3224 |
@Deprecated |
|
3161 | 3225 |
private static class UndoData |
3162 | 3226 |
{ |
3163 | 3227 |
/** Undoable which will set a no-undo buffer to its proper record after a rollback. */ |
new/src/com/goldencode/p2j/persist/ChangeBroker.java 2022-09-01 08:47:22 +0000 | ||
---|---|---|
98 | 98 |
** Use an identity HashSet where possible. |
99 | 99 |
** CA 20220309 Added isQueried(), which checks if a temp-table has any listeners registered for |
100 | 100 |
** events which are a P2JQuery. |
101 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
102 |
** registration is now specific to each type of scopeable. For each case, the block |
|
103 |
** will be registered for scope support (for that particular scopeable) only when |
|
104 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
105 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
106 |
** processing all the scopeables for each and every block. |
|
101 | 107 |
*/ |
102 | 108 | |
103 | 109 |
/* |
... | ... | |
164 | 170 |
import com.goldencode.p2j.persist.orm.*; |
165 | 171 |
import com.goldencode.p2j.security.*; |
166 | 172 |
import com.goldencode.p2j.util.*; |
173 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
167 | 174 | |
168 | 175 |
/** |
169 | 176 |
* A clearing house which notifies interested parties of changes made to |
... | ... | |
253 | 260 |
} |
254 | 261 |
|
255 | 262 |
/** |
256 |
* Register with the {@link com.goldencode.p2j.util.TransactionManager |
|
257 |
* TransactionManager} a factory object which creates instances of this |
|
258 |
* class, so that they can be registered to receive notifications of |
|
259 |
* runtime scope start and finish events. |
|
260 |
* <p> |
|
261 |
* This method should be invoked once during the server bootstrap phase. |
|
262 |
*/ |
|
263 |
static void initialize() |
|
264 |
{ |
|
265 |
TransactionManager.registerScopeableFactory(ChangeBroker::get); |
|
266 |
} |
|
267 |
|
|
268 |
/** |
|
269 | 263 |
* Add a scope to the listeners dictionary whenever a new runtime scope |
270 | 264 |
* opens. |
271 | 265 |
*/ |
... | ... | |
332 | 326 |
} |
333 | 327 |
|
334 | 328 |
/** |
329 |
* Get the {@link ScopeId} for the instance. |
|
330 |
* |
|
331 |
* @return {@link ScopeId#CHANGE_BROKER}. |
|
332 |
*/ |
|
333 |
@Override |
|
334 |
public ScopeId getScopeId() |
|
335 |
{ |
|
336 |
return ScopeId.CHANGE_BROKER; |
|
337 |
} |
|
338 |
|
|
339 |
/** |
|
335 | 340 |
* Register a listener to receive DMO property change notifications. The |
336 | 341 |
* listener will receive notifications of any changes to DMOs of the types |
337 | 342 |
* for which it is registered, as they occur in this scope or in scopes |
new/src/com/goldencode/p2j/persist/CompoundQuery.java 2022-09-01 08:48:30 +0000 | ||
---|---|---|
224 | 224 |
** its own block and not via a QUERY resource). |
225 | 225 |
** IAS 20220510 Resetting activeIndex before iterating over the components for current(LockType) |
226 | 226 |
** IAS 20220707 Resetting nullOuter on new iteration step. |
227 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
228 |
** registration is now specific to each type of scopeable. For each case, the block |
|
229 |
** will be registered for scope support (for that particular scopeable) only when |
|
230 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
231 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
232 |
** processing all the scopeables for each and every block. |
|
227 | 233 |
*/ |
228 | 234 | |
229 | 235 |
/* |
... | ... | |
763 | 769 |
activeIndex = -1; |
764 | 770 |
preselected = false; |
765 | 771 |
|
766 |
int lowestScope = registerRecordChangeListeners();
|
|
772 |
boolean globalScope = registerRecordChangeListeners();
|
|
767 | 773 |
|
768 | 774 |
super.open(); |
769 | 775 |
|
... | ... | |
772 | 778 |
preselectResults(); |
773 | 779 |
} |
774 | 780 |
|
775 |
initReferenceRowSupport(lowestScope);
|
|
781 |
initReferenceRowSupport(globalScope);
|
|
776 | 782 |
} |
777 | 783 |
|
778 | 784 |
/** |
... | ... | |
1880 | 1886 |
* Init structures required to use reference row: create the map of all buffers, register |
1881 | 1887 |
* parameter filters for sub-queries and register this query as a record change listener. |
1882 | 1888 |
* |
1883 |
* @param blockDepth
|
|
1884 |
* Depth of the block at which this query is registered as record change listener.
|
|
1885 |
* <code>0</code> for global scope.
|
|
1889 |
* @param globalScope
|
|
1890 |
* Flag indicating if the block at which this query is registered as record change listener is
|
|
1891 |
* the global scope.
|
|
1886 | 1892 |
*/ |
1887 |
protected void initReferenceRowSupport(int blockDepth)
|
|
1893 |
protected void initReferenceRowSupport(boolean globalScope)
|
|
1888 | 1894 |
{ |
1889 | 1895 |
if (!preselect && buffersMap == null) |
1890 | 1896 |
{ |
... | ... | |
1909 | 1915 |
} |
1910 | 1916 |
|
1911 | 1917 |
ChangeBroker.get().addListener(this); |
1912 |
if (blockDepth == 0)
|
|
1918 |
if (globalScope)
|
|
1913 | 1919 |
{ |
1914 | 1920 |
unregisterOnCleanup = true; |
1915 | 1921 |
} |
... | ... | |
2064 | 2070 |
@SuppressWarnings("unchecked") |
2065 | 2071 |
protected Object[] retrieve(int navigation, LockType lockType, boolean iterating, boolean peek) |
2066 | 2072 |
{ |
2067 |
initReferenceRowSupport(-1);
|
|
2073 |
initReferenceRowSupport(false);
|
|
2068 | 2074 |
|
2069 | 2075 |
Object[] rowData; |
2070 | 2076 |
|
... | ... | |
2398 | 2404 |
/** |
2399 | 2405 |
* Register the query within each component as a record change listener. |
2400 | 2406 |
* |
2401 |
* @return The lowest scope found among all the components' record buffers.
|
|
2407 |
* @return <code>true</code> if the global scope is used for registration.
|
|
2402 | 2408 |
*/ |
2403 |
private int registerRecordChangeListeners()
|
|
2409 |
private boolean registerRecordChangeListeners()
|
|
2404 | 2410 |
{ |
2405 | 2411 |
// Find for each compound query component the most outer scope among |
2406 | 2412 |
// nearest external scope and the outermost scopes of buffers used by |
2407 | 2413 |
// this component and register the component into this scope. |
2408 |
int externalScope = TransactionManager.findNearestExternal();
|
|
2414 |
int externalScope = BufferManager.get().findNearestExternal();
|
|
2409 | 2415 |
int lowestScope = externalScope; |
2410 | 2416 |
|
2411 | 2417 |
for (CompoundComponent comp : getComponents()) |
... | ... | |
2428 | 2434 |
} |
2429 | 2435 |
} |
2430 | 2436 |
|
2431 |
return lowestScope; |
|
2437 |
return lowestScope == 0;
|
|
2432 | 2438 |
} |
2433 | 2439 |
|
2434 | 2440 |
/** |
new/src/com/goldencode/p2j/persist/DataSet.java 2022-09-01 08:48:23 +0000 | ||
---|---|---|
62 | 62 |
** CA 20220106 Fixed CREATE-LIKE when relations are involved, their active flag was not being copied |
63 | 63 |
** properly. |
64 | 64 |
** OM 20220422 Allow Xml/JsonImport to load records into buffer without exposing package private methods. |
65 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the registration |
|
66 |
** is now specific to each type of scopeable. For each case, the block will be registered |
|
67 |
** for scope support (for that particular scopeable) only when the scopeable is 'active' |
|
68 |
** (i.e. unnamed streams or accumulators are used). This allows a lazy registration of |
|
69 |
** scopeables, to avoid the unnecessary overhead of processing all the scopeables for each |
|
70 |
** and every block. |
|
65 | 71 |
*/ |
66 | 72 | |
67 | 73 |
/* |
... | ... | |
403 | 409 |
throw new IllegalStateException("Parameter mode (INPUT/OUTPUT) was not specified!"); |
404 | 410 |
} |
405 | 411 |
|
412 |
DataSetManager.registerScopeable(); |
|
413 |
|
|
406 | 414 |
StaticDataSet localDS = (StaticDataSet) dsTarget; |
407 | 415 |
if (!dsSrc.isRemoteParameter()) |
408 | 416 |
{ |
... | ... | |
638 | 646 |
throw new IllegalStateException("Parameter mode (INPUT/OUTPUT) was not specified!"); |
639 | 647 |
} |
640 | 648 |
|
649 |
DataSetManager.registerScopeable(); |
|
650 |
|
|
641 | 651 |
if (output) |
642 | 652 |
{ |
643 | 653 |
TransactionManager.registerCurrent(dsHandle); |
new/src/com/goldencode/p2j/persist/DataSetManager.java 2022-09-01 08:51:46 +0000 | ||
---|---|---|
2 | 2 |
** Module : DataSetManager.java |
3 | 3 |
** Abstract : Manages all the DataSets, taking care for matching shared ones. |
4 | 4 |
** |
5 |
** Copyright (c) 2019-2020, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2019-2022, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- ---------------------------------Description--------------------------------- |
8 | 8 |
** 001 OM 20190403 Created initial version. |
... | ... | |
11 | 11 |
** OM 20190731 Added REFERENCE-ONLY support. |
12 | 12 |
** 004 CA 20200110 More fixes for DATASET parameters and resource delete. |
13 | 13 |
** 005 CA 20201003 Allow dictionaries with an identity map. |
14 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the registration |
|
15 |
** is now specific to each type of scopeable. For each case, the block will be registered |
|
16 |
** for scope support (for that particular scopeable) only when the scopeable is 'active' |
|
17 |
** (i.e. unnamed streams or accumulators are used). This allows a lazy registration of |
|
18 |
** scopeables, to avoid the unnecessary overhead of processing all the scopeables for each |
|
19 |
** and every block. |
|
14 | 20 |
*/ |
15 | 21 | |
16 | 22 |
/* |
... | ... | |
70 | 76 | |
71 | 77 |
import com.goldencode.p2j.security.*; |
72 | 78 |
import com.goldencode.p2j.util.*; |
79 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
73 | 80 | |
74 | 81 |
import java.util.*; |
75 | 82 | |
... | ... | |
116 | 123 |
|
117 | 124 |
/** A dictionary of BY-REFERENCE dataset parameters. */ |
118 | 125 |
private final ScopedDictionary<DataSet, Integer> byReferenceParameters = new ScopedDictionary<>(); |
126 | ||
127 |
/** The transaction helper. */ |
|
128 |
private final TransactionManager.TransactionHelper tm; |
|
119 | 129 |
|
120 | 130 |
/** |
121 | 131 |
* Default c'tor. Marks dictionaries which can use identity maps. |
122 | 132 |
*/ |
123 | 133 |
private DataSetManager() |
124 | 134 |
{ |
135 |
tm = TransactionManager.getTransactionHelper(); |
|
125 | 136 |
dshOutputParams.setIdentityKeys(true); |
126 | 137 |
byReferenceParameters.setIdentityKeys(true); |
138 |
|
|
139 |
// there is a bug with static datasets: instead of registering as 'pending' for next scope, they are |
|
140 |
// registering in the callee's scope... so, for now, push an 'implicit' scope here. |
|
141 |
scopeStart(); |
|
127 | 142 |
} |
128 | 143 |
|
129 | 144 |
/** |
... | ... | |
152 | 167 |
return instance.get(); |
153 | 168 |
} |
154 | 169 |
|
155 |
|
|
156 | 170 |
/** |
157 |
* Register with the {@link com.goldencode.p2j.util.TransactionManager |
|
158 |
* TransactionManager} a factory object which creates instances of this |
|
159 |
* class, so that they can be registered to receive notifications of |
|
160 |
* runtime scope start and finish events. |
|
161 |
* <p> |
|
162 |
* This method should be invoked once during the server bootstrap phase. |
|
171 |
* Register the {@link DataSetManager} for scope notifications at the current block. |
|
163 | 172 |
*/ |
164 |
static void initialize()
|
|
173 |
public static void registerScopeable()
|
|
165 | 174 |
{ |
166 |
TransactionManager.registerScopeableFactory(DataSetManager::instance); |
|
175 |
DataSetManager mgr = instance(); |
|
176 |
mgr.tm.registerBlockScopeable(mgr); |
|
167 | 177 |
} |
168 | 178 |
|
169 | 179 |
/** |
... | ... | |
180 | 190 |
*/ |
181 | 191 |
public void register(DataSet dataSet, String legacyName, boolean isShared, boolean isNew) |
182 | 192 |
{ |
193 |
tm.registerPendingScopeable(this); |
|
194 |
|
|
183 | 195 |
if (!dataSet._dynamic()) |
184 | 196 |
{ |
185 | 197 |
registry.addEntry(false, legacyName.toLowerCase(), dataSet); |
... | ... | |
252 | 264 |
} |
253 | 265 |
|
254 | 266 |
/** |
267 |
* Get the {@link ScopeId} for the instance. |
|
268 |
* |
|
269 |
* @return {@link ScopeId#DATA_SET_MANAGER}. |
|
270 |
*/ |
|
271 |
@Override |
|
272 |
public ScopeId getScopeId() |
|
273 |
{ |
|
274 |
return ScopeId.DATA_SET_MANAGER; |
|
275 |
} |
|
276 |
|
|
277 |
/** |
|
255 | 278 |
* Check if the given dataset is passed as a BY-REFERENCE parameter. |
256 | 279 |
* |
257 | 280 |
* @param ds |
new/src/com/goldencode/p2j/persist/Persistence.java 2022-09-01 08:47:44 +0000 | ||
---|---|---|
569 | 569 |
** IAS 20220608 Provide additional information in reportUDFVersion(). |
570 | 570 |
** IAS 20220712 Create missing UDFs |
571 | 571 |
** IAS 20220816 Do not use 'udf' schema for non-PostgreSQL UDFs |
572 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
573 |
** registration is now specific to each type of scopeable. For each case, the block |
|
574 |
** will be registered for scope support (for that particular scopeable) only when |
|
575 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
576 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
577 |
** processing all the scopeables for each and every block. |
|
572 | 578 |
*/ |
573 | 579 | |
574 | 580 |
/* |
... | ... | |
819 | 825 |
* Initialize various infrastructure components of the persistence framework: |
820 | 826 |
* <ul> |
821 | 827 |
* <li>{@code DataTypeHelper}, which is used when preprocessing FQL where clauses. |
822 |
* <li>{@code BufferManager}, which tracks open buffers and transactions. |
|
823 |
* <li>{@code ChangeBroker}, which dispatches notifications about changes to DMO properties. |
|
824 | 828 |
* <li>{@code DatabaseManager}, which configures the ORM environment for the databases |
825 | 829 |
* to which the framework connects. |
826 | 830 |
* <li>{@code P2OLookup}, instances of which are used for runtime, on-the-fly query and |
... | ... | |
835 | 839 |
* if any error is encountered initializing the persistence framework. |
836 | 840 |
* |
837 | 841 |
* @see DataTypeHelper#initialize() |
838 |
* @see BufferManager#initialize() |
|
839 |
* @see ChangeBroker#initialize() |
|
840 | 842 |
* @see DatabaseManager#initialize() |
841 | 843 |
* @see TemporaryDatabaseManager#initialize() |
842 |
* @see DataSetManager#initialize() |
|
843 | 844 |
* @see P2OLookup#initialize() |
844 | 845 |
*/ |
845 | 846 |
public static void initialize() |
846 | 847 |
throws PersistenceException |
847 | 848 |
{ |
848 | 849 |
DataTypeHelper.initialize(); |
849 |
BufferManager.initialize(); |
|
850 |
ChangeBroker.initialize(); |
|
851 | 850 |
TemporaryDatabaseManager.initialize(); |
852 | 851 |
DatabaseManager.initialize(); |
853 |
DataSetManager.initialize(); |
|
854 | 852 |
|
855 | 853 |
// if runtime conversion services are required, initialize schema lookup resources |
856 | 854 |
if (ConversionPool.isInitialized()) |
new/src/com/goldencode/p2j/persist/RecordBuffer.java 2022-09-01 08:47:37 +0000 | ||
---|---|---|
1217 | 1217 |
** must be used, as the buffer instance may be proxied. Fixed OM/20220707. |
1218 | 1218 |
** OM 20220809 Use a temporary virtual scope while invoking the db triggers to block the |
1219 | 1219 |
** release() to be recursively invoked at the end of a trigger(). |
1220 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
1221 |
** registration is now specific to each type of scopeable. For each case, the block |
|
1222 |
** will be registered for scope support (for that particular scopeable) only when |
|
1223 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
1224 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
1225 |
** processing all the scopeables for each and every block. |
|
1220 | 1226 |
*/ |
1221 | 1227 | |
1222 | 1228 |
/* |
... | ... | |
3783 | 3789 |
} |
3784 | 3790 |
|
3785 | 3791 |
// heuristically convert from SQL name to legacy name |
3786 |
Iterator<Property> fields = buffer.dmoInfo.getFields(false);
|
|
3792 |
Iterator<Property> fields = buffer.getDmoInfo().getFields(false);
|
|
3787 | 3793 |
while (fields.hasNext()) |
3788 | 3794 |
{ |
3789 | 3795 |
Property prop = fields.next(); |
... | ... | |
3940 | 3946 |
BufferReference srcProxy = (BufferReference) srcDmo; |
3941 | 3947 |
RecordBuffer srcBuf = srcProxy.buffer(); |
3942 | 3948 |
RecordBuffer dstBuf = dstProxy.buffer(); |
3949 |
dstBuf.bufferManager.registerDirtyBuffer(dstBuf); |
|
3943 | 3950 |
|
3944 | 3951 |
srcBuf.initialize(); |
3945 | 3952 |
dstBuf.initialize(); |
... | ... | |
4231 | 4238 |
return new logical(false); |
4232 | 4239 |
} |
4233 | 4240 |
|
4241 |
dstBuf.bufferManager.registerDirtyBuffer(dstBuf); |
|
4242 |
|
|
4234 | 4243 |
boolean created = false; |
4235 | 4244 |
Record dstRec = dstBuf.getCurrentRecord(); |
4236 | 4245 |
if (dstRec == null) |
... | ... | |
7549 | 7558 |
*/ |
7550 | 7559 |
protected void openScopeAt(int blockDepth) |
7551 | 7560 |
{ |
7561 |
// TODO: blockDepth param is always zero... |
|
7562 |
|
|
7552 | 7563 |
// Register this scope with the buffer manager. |
7553 | 7564 |
bufferManager.openScopeAt(blockDepth, this); |
7554 | 7565 |
|
new/src/com/goldencode/p2j/persist/trigger/DatabaseTriggerManager.java 2022-09-01 08:49:05 +0000 | ||
---|---|---|
55 | 55 |
** TW 20220803 Error-status:error must be set for return error in method, while return error |
56 | 56 |
** in old-style ABL function must remain the same. Refs: #6567. |
57 | 57 |
** TW 20220817 Error-status:error must be set for return error in static method. |
58 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
59 |
** registration is now specific to each type of scopeable. For each case, the block |
|
60 |
** will be registered for scope support (for that particular scopeable) only when |
|
61 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
62 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
63 |
** processing all the scopeables for each and every block. |
|
58 | 64 |
*/ |
59 | 65 | |
60 | 66 |
/* |
... | ... | |
117 | 123 |
import com.goldencode.p2j.security.*; |
118 | 124 |
import com.goldencode.p2j.util.*; |
119 | 125 |
import com.goldencode.p2j.util.LogHelper; |
126 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
127 | ||
120 | 128 |
import java.lang.reflect.*; |
121 | 129 |
import java.util.*; |
122 | 130 |
import java.util.logging.Level; |
... | ... | |
166 | 174 |
*/ |
167 | 175 |
private DatabaseTriggerManager() |
168 | 176 |
{ |
169 |
// I want to receive enter/leave bloc events |
|
170 |
tm.registerScopeable(this); |
|
171 | 177 |
if (LOG.isLoggable(Level.FINE)) |
172 | 178 |
{ |
173 | 179 |
LOG.log(Level.FINE, "DatabaseTriggerManager registered with TransactionManager."); |
... | ... | |
456 | 462 |
boolean hasOldBuffer) |
457 | 463 |
{ |
458 | 464 |
DatabaseTriggerManager manager = get(); |
465 |
manager.tm.registerTopLevelScopeable(manager); |
|
466 |
|
|
459 | 467 |
if (manager.stack.isEmpty()) |
460 | 468 |
{ |
461 | 469 |
// sanity check failed |
... | ... | |
558 | 566 |
throw new IllegalArgumentException("Use this form of register only for ASSIGN triggers."); |
559 | 567 |
} |
560 | 568 |
DatabaseTriggerManager manager = get(); |
569 |
manager.tm.registerTopLevelScopeable(manager); |
|
570 |
|
|
561 | 571 |
if (manager.stack.isEmpty()) |
562 | 572 |
{ |
563 | 573 |
// sanity check failed |
... | ... | |
601 | 611 |
} |
602 | 612 |
|
603 | 613 |
DatabaseTriggerManager manager = get(); |
614 |
manager.tm.registerTopLevelScopeable(manager); |
|
615 |
|
|
604 | 616 |
if (manager.stack.isEmpty()) |
605 | 617 |
{ |
606 | 618 |
// sanity check failed |
... | ... | |
633 | 645 |
} |
634 | 646 |
|
635 | 647 |
DatabaseTriggerManager manager = get(); |
648 |
manager.tm.registerTopLevelScopeable(manager); |
|
649 |
|
|
636 | 650 |
if (manager.stack.isEmpty()) |
637 | 651 |
{ |
638 | 652 |
// sanity check failed |
... | ... | |
656 | 670 |
public static boolean disableDumpTriggers(Class<? extends Buffer> bufferCls) |
657 | 671 |
{ |
658 | 672 |
DatabaseTriggerManager manager = get(); |
673 |
manager.tm.registerTopLevelScopeable(manager); |
|
674 |
|
|
659 | 675 |
if (manager.stack.isEmpty()) |
660 | 676 |
{ |
661 | 677 |
return false; |
... | ... | |
697 | 713 |
boolean allowReplication) |
698 | 714 |
{ |
699 | 715 |
DatabaseTriggerManager manager = get(); |
716 |
manager.tm.registerTopLevelScopeable(manager); |
|
717 |
|
|
700 | 718 |
if (manager.stack.isEmpty()) |
701 | 719 |
{ |
702 | 720 |
return false; |
... | ... | |
910 | 928 |
public void scopeStart() |
911 | 929 |
{ |
912 | 930 |
// triggers get notifications at all top level blocks |
913 |
if (tm.isTopLevelBlock()) |
|
914 |
{ |
|
915 |
stack.addFirst(new TriggerBlockLayer()); // push(); |
|
916 |
} |
|
931 |
stack.addFirst(new TriggerBlockLayer()); // push(); |
|
917 | 932 |
} |
918 | 933 |
|
919 | 934 |
/** |
... | ... | |
926 | 941 |
} |
927 | 942 |
|
928 | 943 |
/** |
944 |
* Get the {@link ScopeId} for the instance. |
|
945 |
* |
|
946 |
* @return {@link ScopeId#DATABASE_TRIGGER_MANAGER}. |
|
947 |
*/ |
|
948 |
@Override |
|
949 |
public ScopeId getScopeId() |
|
950 |
{ |
|
951 |
return ScopeId.DATABASE_TRIGGER_MANAGER; |
|
952 |
} |
|
953 |
|
|
954 |
/** |
|
929 | 955 |
* Provides a notification that a scope is about to be exited. The manager only acts on |
930 | 956 |
* top-level scope. Each time a scope is exited a the last layer of triggers is removed from |
931 | 957 |
* internal stack. |
... | ... | |
934 | 960 |
public void scopeFinished() |
935 | 961 |
{ |
936 | 962 |
// triggers get notifications at all top level blocks |
937 |
if (tm.isTopLevelBlock()) |
|
938 |
{ |
|
939 |
if (stack.isEmpty()) |
|
940 |
{ |
|
941 |
LOG.log(Level.WARNING, "Invalid scope finished."); |
|
942 |
} |
|
943 |
else |
|
944 |
{ |
|
945 |
stack.removeFirst(); // pop(); |
|
946 |
} |
|
963 |
if (stack.isEmpty()) |
|
964 |
{ |
|
965 |
LOG.log(Level.WARNING, "Invalid scope finished."); |
|
966 |
} |
|
967 |
else |
|
968 |
{ |
|
969 |
stack.removeFirst(); // pop(); |
|
947 | 970 |
} |
948 | 971 |
} |
949 | 972 |
|
new/src/com/goldencode/p2j/ui/GenericFrame.java 2022-09-01 08:49:01 +0000 | ||
---|---|---|
955 | 955 |
** widget is explicitly specified. |
956 | 956 |
** EVL 20220809 Fixed the regression from recent HIDDEN attribute reset change. Only widgets |
957 | 957 |
** defined in DISPLAY statement should be affected. |
958 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
959 |
** registration is now specific to each type of scopeable. For each case, the block |
|
960 |
** will be registered for scope support (for that particular scopeable) only when |
|
961 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
962 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
963 |
** processing all the scopeables for each and every block. |
|
958 | 964 |
*/ |
959 | 965 | |
960 | 966 |
/* |
... | ... | |
1849 | 1855 |
public Object invoke(Object proxy, Method method, Object[] args) |
1850 | 1856 |
throws Throwable |
1851 | 1857 |
{ |
1858 |
// frame is accessed, register scopeable |
|
1859 |
TransactionManager.registerBlockScopeable(LogicalTerminal.getInstance()); |
|
1860 |
|
|
1852 | 1861 |
int op = -1; |
1853 | 1862 |
String widgetName = null; |
1854 | 1863 | |
... | ... | |
8721 | 8730 |
// push down the screen definition |
8722 | 8731 |
if (force) |
8723 | 8732 |
{ |
8733 |
TransactionManager.registerBlockScopeable(LogicalTerminal.getInstance()); |
|
8734 | ||
8724 | 8735 |
// synchronous push |
8725 | 8736 |
ScreenDefinition[] sd = new ScreenDefinition[] {frameDef}; |
8726 | 8737 |
LogicalTerminal.pushScreenDefinition(sd); |
new/src/com/goldencode/p2j/ui/LogicalTerminal.java 2022-09-01 08:48:53 +0000 | ||
---|---|---|
995 | 995 |
** TW 20220803 Error-status:error must be set for return error in method, while return error |
996 | 996 |
** in old-style ABL function must remain the same. Refs: #6567. |
997 | 997 |
** TW 20220817 Error-status:error must be set for return error in static method. |
998 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
999 |
** registration is now specific to each type of scopeable. For each case, the block |
|
1000 |
** will be registered for scope support (for that particular scopeable) only when |
|
1001 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
1002 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
1003 |
** processing all the scopeables for each and every block. |
|
998 | 1004 |
*/ |
999 | 1005 | |
1000 | 1006 |
/* |
... | ... | |
1078 | 1084 |
import com.goldencode.p2j.util.*; |
1079 | 1085 |
import com.goldencode.p2j.util.ErrorManager; |
1080 | 1086 |
import com.goldencode.p2j.util.ErrorManager.*; |
1087 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
1081 | 1088 |
import com.goldencode.p2j.util.LogHelper; |
1082 | 1089 |
import com.goldencode.p2j.util.SocketImpl; |
1083 | 1090 |
import com.goldencode.p2j.util.Text; |
... | ... | |
1703 | 1710 |
} |
1704 | 1711 |
|
1705 | 1712 |
LogicalTerminal lt = locate(); |
1706 |
lt.scopeTrack.forceHiding();
|
|
1713 |
lt.forceHiding(); |
|
1707 | 1714 |
lt.client.hideAll(noPause, targetWindowWorker(hWin, false)); |
1708 | 1715 |
|
1709 | 1716 |
// TODO get frames from target window? |
... | ... | |
9364 | 9371 |
|
9365 | 9372 |
LogicalTerminal lt = locate(); |
9366 | 9373 |
|
9367 |
lt.scopeTrack.frameViewed(frame);
|
|
9374 |
lt.frameViewed(frame); |
|
9368 | 9375 |
frame.setHadView(); |
9369 | 9376 | |
9370 | 9377 |
// refresh editable frames list |
... | ... | |
9405 | 9412 |
|
9406 | 9413 |
LogicalTerminal lt = locate(); |
9407 | 9414 |
|
9408 |
lt.scopeTrack.frameViewed(frame);
|
|
9415 |
lt.frameViewed(frame); |
|
9409 | 9416 |
frame.setHadView(); |
9410 | 9417 | |
9411 | 9418 |
// refresh editable frames list |
... | ... | |
9519 | 9526 |
ScreenBuffer[] frameBuf = (frame == null) ? null : lt.getEditableServerScreenBuffers(frame); |
9520 | 9527 |
int windowId = (frame == null) ? WindowConfig.RESOLVE_WINDOW : frame.getWindowId(); |
9521 | 9528 |
|
9522 |
lt.scopeTrack.frameViewed(frame);
|
|
9529 |
lt.frameViewed(frame); |
|
9523 | 9530 |
FieldGroup fg; |
9524 | 9531 |
if (frame != null) |
9525 | 9532 |
{ |
... | ... | |
9549 | 9556 |
{ |
9550 | 9557 |
LogicalTerminal lt = locate(); |
9551 | 9558 |
|
9552 |
lt.scopeTrack.frameViewed(frame);
|
|
9559 |
lt.frameViewed(frame); |
|
9553 | 9560 |
|
9554 | 9561 |
view(frame.getFrameId(), |
9555 | 9562 |
lt.getEditableServerScreenBuffers(frame), |
... | ... | |
9577 | 9584 |
{ |
9578 | 9585 |
LogicalTerminal lt = locate(); |
9579 | 9586 |
|
9580 |
lt.scopeTrack.frameViewed(frame);
|
|
9587 |
lt.frameViewed(frame); |
|
9581 | 9588 |
|
9582 | 9589 |
view(frame.getFrameId(), |
9583 | 9590 |
lt.getEditableServerScreenBuffers(frame), |
... | ... | |
9625 | 9632 |
{ |
9626 | 9633 |
LogicalTerminal lt = locate(); |
9627 | 9634 |
|
9628 |
lt.scopeTrack.frameViewed(frame);
|
|
9635 |
lt.frameViewed(frame); |
|
9629 | 9636 |
|
9630 | 9637 |
WidgetConfig[] wcfgs = lt.client.view(frame.getFrameId(), |
9631 | 9638 |
lt.getEditableServerScreenBuffers(frame), |
... | ... | |
9669 | 9676 |
{ |
9670 | 9677 |
LogicalTerminal lt = locate(); |
9671 | 9678 |
|
9672 |
lt.scopeTrack.frameViewed(frame);
|
|
9679 |
lt.frameViewed(frame); |
|
9673 | 9680 |
|
9674 | 9681 |
FieldGroup fg = frame.getFieldGroup(); |
9675 | 9682 |
|
... | ... | |
9724 | 9731 |
{ |
9725 | 9732 |
LogicalTerminal lt = locate(); |
9726 | 9733 |
|
9727 |
lt.scopeTrack.frameViewed(frame);
|
|
9734 |
lt.frameViewed(frame); |
|
9728 | 9735 |
|
9729 | 9736 |
WidgetConfig[] wcfgs = lt.client.view(frame.getFrameId(), |
9730 | 9737 |
lt.getEditableServerScreenBuffers(frame), |
... | ... | |
9760 | 9767 |
{ |
9761 | 9768 |
LogicalTerminal lt = locate(); |
9762 | 9769 |
|
9763 |
lt.scopeTrack.frameViewed(frame);
|
|
9770 |
lt.frameViewed(frame); |
|
9764 | 9771 |
|
9765 | 9772 |
view(frame.getFrameId(), |
9766 | 9773 |
frameBuf, |
... | ... | |
9810 | 9817 |
// call the client |
9811 | 9818 |
try |
9812 | 9819 |
{ |
9813 |
lt.scopeTrack.frameViewed(frame);
|
|
9820 |
lt.frameViewed(frame); |
|
9814 | 9821 |
|
9815 | 9822 |
int[] tabItemList = frame.updateTabItemsList(widgetIds, UpdatesOp.PROMPT_FOR); |
9816 | 9823 |
|
... | ... | |
10155 | 10162 |
// we haven't had the chance to mark the next partition yet because |
10156 | 10163 |
// scopeStart() won't be called until the business logic initializer |
10157 | 10164 |
// is complete |
10158 |
locate().level2definitions.add(frameDef); |
|
10165 |
LogicalTerminal lt = locate(); |
|
10166 |
lt.level2definitions.add(frameDef); |
|
10167 |
lt.tm.registerPendingScopeable(lt); |
|
10159 | 10168 |
} |
10160 | 10169 | |
10161 | 10170 |
/** |
... | ... | |
10171 | 10180 |
// we haven't had the chance to mark the next partition yet because |
10172 | 10181 |
// scopeStart() won't be called until the business logic initializer |
10173 | 10182 |
// is complete |
10174 |
locate().level2descriptions.add(menuDescr); |
|
10183 |
LogicalTerminal lt = locate(); |
|
10184 |
lt.level2descriptions.add(menuDescr); |
|
10185 |
lt.tm.registerPendingScopeable(lt); |
|
10175 | 10186 |
} |
10176 | 10187 |
|
10177 | 10188 |
/** |
... | ... | |
10193 | 10204 |
public static void processDeferredPush(boolean fromLevel2) |
10194 | 10205 |
{ |
10195 | 10206 |
LogicalTerminal lt = locate(); |
10207 |
lt.tm.registerBlockScopeable(lt); |
|
10208 | ||
10196 | 10209 |
if (fromLevel2) |
10197 | 10210 |
{ |
10198 | 10211 |
lt.definitions.markPartition(); |
... | ... | |
11372 | 11385 |
*/ |
11373 | 11386 |
static void deregisterFrame(int frameId) |
11374 | 11387 |
{ |
11375 |
locate().deregisterFrameInt(frameId); |
|
11388 |
LogicalTerminal lt = locate(); |
|
11389 |
lt.tm.registerBlockScopeable(lt); |
|
11390 | ||
11391 |
lt.deregisterFrameInt(frameId); |
|
11376 | 11392 |
} |
11377 | 11393 |
|
11378 | 11394 |
/** |
... | ... | |
11815 | 11831 |
return frameRegistry.get(frameId); |
11816 | 11832 |
} |
11817 | 11833 |
} |
11834 |
|
|
11835 |
/** |
|
11836 |
* Notify scope that frame is viewed. |
|
11837 |
* <p> |
|
11838 |
* This also registeres {@link LogicalTerminal} for scope notifications at the current block. |
|
11839 |
* |
|
11840 |
* @param frame |
|
11841 |
* Frame which is about to be viewed. |
|
11842 |
*/ |
|
11843 |
private void frameViewed(GenericFrame frame) |
|
11844 |
{ |
|
11845 |
tm.registerBlockScopeable(this); |
|
11846 |
|
|
11847 |
scopeTrack.frameViewed(frame); |
|
11848 |
} |
|
11818 | 11849 | |
11819 | 11850 |
/** |
11851 |
* Clear map of viewed frames. |
|
11852 |
* <p> |
|
11853 |
* This also registeres {@link LogicalTerminal} for scope notifications at the current block. |
|
11854 |
*/ |
|
11855 |
private void forceHiding() |
|
11856 |
{ |
|
11857 |
tm.registerBlockScopeable(this); |
|
11858 |
|
|
11859 |
scopeTrack.forceHiding(); |
|
11860 |
} |
|
11861 |
|
|
11862 |
/** |
|
11820 | 11863 |
* Save the {@link UIStatement} running for each registered frame. |
11821 | 11864 |
* |
11822 | 11865 |
* @return A map with each frame's UI statement. |
... | ... | |
13298 | 13341 |
} |
13299 | 13342 |
|
13300 | 13343 |
/** |
13301 |
* Register with the {@link com.goldencode.p2j.util.TransactionManager TransactionManager} a |
|
13302 |
* factory object which creates instances of this class, so that they can be registered to |
|
13303 |
* receive notifications of runtime scope start and finish events. |
|
13304 |
* <p> |
|
13305 |
* This method should be invoked once during the server bootstrap phase. |
|
13306 |
* <p> |
|
13307 |
* The registered factory functions conditionally. It uses the {@link |
|
13308 |
* TransactionManager#_isHeadless()} to check whether the context has been declared headless. |
|
13309 |
*/ |
|
13310 |
public static void initialize() |
|
13311 |
{ |
|
13312 |
TransactionManager.registerScopeableFactory( |
|
13313 |
() -> TransactionManager._isHeadless() ? null : LogicalTerminal.locate() |
|
13314 |
); |
|
13315 |
} |
|
13316 |
|
|
13317 |
/** |
|
13318 | 13344 |
* Process a notification that a new block scope is about to be entered. |
13319 | 13345 |
* <p> |
13320 | 13346 |
* In the Logical Terminal, a new top level block scope causes creation of |
... | ... | |
13325 | 13351 |
@Override |
13326 | 13352 |
public void scopeStart() |
13327 | 13353 |
{ |
13354 |
// scopeable registration is done in different places - if changes are made, ensure that scopeable |
|
13355 |
// support is registered properly. |
|
13356 |
|
|
13328 | 13357 |
// register at each scope, it is important to instantiate the scope |
13329 | 13358 |
// processor BEFORE the state.interactions counter is reset below |
13330 | 13359 |
tm.registerFinalizable(new ScopeProcessor(), false); |
... | ... | |
13342 | 13371 |
state.interactions = 0; |
13343 | 13372 |
} |
13344 | 13373 |
|
13345 |
// make sure that the global block gets a special notification - but only for non-appserver sessions. |
|
13346 |
if (tm.isGlobalBlock() && !tm.isRemote()) |
|
13347 |
{ |
|
13348 |
Finalizable cleaner = new Finalizable() |
|
13349 |
{ |
|
13350 |
@Override |
|
13351 |
public void finished() |
|
13352 |
{ |
|
13353 |
pauseBeforeEnd(tm.isProcessingQuit()); |
|
13354 |
} |
|
13355 |
|
|
13356 |
@Override |
|
13357 |
public void iterate() |
|
13358 |
{ |
|
13359 |
// nothing to do here |
|
13360 |
} |
|
13361 |
|
|
13362 |
@Override |
|
13363 |
public void retry() |
|
13364 |
{ |
|
13365 |
// nothing to do here |
|
13366 |
} |
|
13367 |
|
|
13368 |
@Override |
|
13369 |
public void deleted() |
|
13370 |
{ |
|
13371 |
// nothing to do here |
|
13372 |
} |
|
13373 |
}; |
|
13374 |
|
|
13375 |
tm.registerFinalizable(cleaner, true); |
|
13376 |
} |
|
13377 | ||
13378 | 13374 |
// add a new scope for each top-level block |
13379 | 13375 |
if (tm.isTopLevelBlock()) |
13380 | 13376 |
{ |
... | ... | |
13463 | 13459 |
} |
13464 | 13460 |
|
13465 | 13461 |
/** |
13462 |
* Get the {@link ScopeId} for the instance. |
|
13463 |
* |
|
13464 |
* @return {@link ScopeId#LOGICAL_TERMINAL}. |
|
13465 |
*/ |
|
13466 |
@Override |
|
13467 |
public ScopeId getScopeId() |
|
13468 |
{ |
|
13469 |
return ScopeId.LOGICAL_TERMINAL; |
|
13470 |
} |
|
13471 |
|
|
13472 |
/** |
|
13466 | 13473 |
* Called by the protocol driver to obtain the latest state that should |
13467 | 13474 |
* be sent to the other side of the connection. This is called just |
13468 | 13475 |
* before a "real" message is sent and any changes provided will be |
... | ... | |
13589 | 13596 |
|
13590 | 13597 |
if (cs.deregister != null) |
13591 | 13598 |
{ |
13599 |
tm.registerBlockScopeable(this); |
|
13600 | ||
13592 | 13601 |
for (int i : cs.deregister) |
13593 | 13602 |
{ |
13594 | 13603 |
deregisterFrameInt(i); |
... | ... | |
13605 | 13614 |
|
13606 | 13615 |
if (cs.wrapped != null && scopeTrack != null) |
13607 | 13616 |
{ |
13617 |
tm.registerBlockScopeable(this); |
|
13618 |
|
|
13608 | 13619 |
for (int id : cs.wrapped) |
13609 | 13620 |
{ |
13610 | 13621 |
scopeTrack.frameWrapped(id); |
new/src/com/goldencode/p2j/ui/MenuContainerWidget.java 2022-09-01 08:52:28 +0000 | ||
---|---|---|
2 | 2 |
** Module : MenuContainerWidget.java |
3 | 3 |
** Abstract : The base class for MenuWidget and SubMenuWidget. |
4 | 4 |
** |
5 |
** Copyright (c) 2015-2020, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2015-2022, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- ---------------------------------Description---------------------------------- |
8 | 8 |
** 001 VIG 20150115 Created initial version. |
... | ... | |
34 | 34 |
** EVL 20201021 More optimization for getAttr() usage or widget ID getting. |
35 | 35 |
** EVL 20201022 Optimized attributes flush implementation. |
36 | 36 |
** CA 20201117 Do not use resourceDelete to delete the widget - use the delete() API for this code. |
37 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the registration |
|
38 |
** is now specific to each type of scopeable. For each case, the block will be registered |
|
39 |
** for scope support (for that particular scopeable) only when the scopeable is 'active' |
|
40 |
** (i.e. unnamed streams or accumulators are used). This allows a lazy registration of |
|
41 |
** scopeables, to avoid the unnecessary overhead of processing all the scopeables for each |
|
42 |
** and every block. |
|
37 | 43 |
*/ |
38 | 44 |
/* |
39 | 45 |
** This program is free software: you can redistribute it and/or modify |
... | ... | |
494 | 500 |
// push down the screen definition |
495 | 501 |
if (force) |
496 | 502 |
{ |
503 |
TransactionManager.registerBlockScopeable(LogicalTerminal.getInstance()); |
|
504 | ||
497 | 505 |
// synchronous push |
498 | 506 |
MenuDescription[] sd = new MenuDescription[] {root.menuDef}; |
499 | 507 |
LogicalTerminal.pushMenuDescription(sd); |
new/src/com/goldencode/p2j/ui/TriggerManager.java 2022-09-01 08:48:45 +0000 | ||
---|---|---|
56 | 56 |
** the resource gets deleted (including widgets). |
57 | 57 |
** CA 20210917 Javadoc fixes. |
58 | 58 |
** SBI 20220126 Fixed scopeFinished to add preserved events before all events from the target list. |
59 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
60 |
** registration is now specific to each type of scopeable. For each case, the block |
|
61 |
** will be registered for scope support (for that particular scopeable) only when |
|
62 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
63 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
64 |
** processing all the scopeables for each and every block. |
|
59 | 65 |
*/ |
60 | 66 | |
61 | 67 |
/* |
... | ... | |
190 | 196 |
EventList events, |
191 | 197 |
int tid) |
192 | 198 |
{ |
199 |
TransactionManager.registerBlockScopeable(LogicalTerminal.getInstance()); |
|
200 | ||
193 | 201 |
events.setTriggerId(tid); |
194 | 202 | |
195 | 203 |
// insert the latest trigger def at the front of the list. all created triggers are saved, |
... | ... | |
261 | 269 |
@SuppressWarnings("unchecked") |
262 | 270 |
public static void deregister(ScopedDictionary<?,?> registry, EventList el) |
263 | 271 |
{ |
272 |
TransactionManager.registerBlockScopeable(LogicalTerminal.getInstance()); |
|
273 | ||
264 | 274 |
LinkedList<EventList> registryScope = null; |
265 | 275 | |
266 | 276 |
// DEBUG: System.err.printf("DEREGISTER\nBEFORE %s", dumpRegistry(registry)); |
new/src/com/goldencode/p2j/util/AbstractParameter.java 2022-09-01 08:54:12 +0000 | ||
---|---|---|
3 | 3 |
** Abstract : Common logic for assigns [input-]output parameter values (database fields and normal |
4 | 4 |
** variables) upon exit from procedure/function |
5 | 5 |
** |
6 |
** Copyright (c) 2015-2021, Golden Code Development Corporation.
|
|
6 |
** Copyright (c) 2015-2022, Golden Code Development Corporation.
|
|
7 | 7 |
** |
8 | 8 |
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------- |
9 | 9 |
** 001 OM 20150702 First version based on extracted code form AbstractSimpleParameter and |
... | ... | |
18 | 18 |
** in the parameter instance must be replaced. |
19 | 19 |
** CA 20210609 Reworked INPUT/INPUT-OUTPUT parameters to a new approach, where they are explicitly |
20 | 20 |
** initialized at the method's execution, and not at the caller's arguments. |
21 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the registration |
|
22 |
** is now specific to each type of scopeable. For each case, the block will be registered |
|
23 |
** for scope support (for that particular scopeable) only when the scopeable is 'active' |
|
24 |
** (i.e. unnamed streams or accumulators are used). This allows a lazy registration of |
|
25 |
** scopeables, to avoid the unnecessary overhead of processing all the scopeables for each |
|
26 |
** and every block. |
|
21 | 27 |
*/ |
22 | 28 |
/* |
23 | 29 |
** This program is free software: you can redistribute it and/or modify |
... | ... | |
76 | 82 | |
77 | 83 |
import com.goldencode.p2j.persist.*; |
78 | 84 |
import com.goldencode.p2j.security.*; |
85 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
86 | ||
79 | 87 |
import java.lang.reflect.*; |
80 | 88 |
import java.util.*; |
81 | 89 |
import java.util.logging.*; |
... | ... | |
338 | 346 |
} |
339 | 347 |
|
340 | 348 |
/** |
349 |
* Get the {@link ScopeId} for the instance. |
|
350 |
* |
|
351 |
* @return <code>null</code>, as the notification is done via {@link BufferManager}. |
|
352 |
*/ |
|
353 |
@Override |
|
354 |
public ScopeId getScopeId() |
|
355 |
{ |
|
356 |
// no explicit registration is done, this is called via BufferManager |
|
357 |
return null; |
|
358 |
} |
|
359 |
|
|
360 |
/** |
|
341 | 361 |
* Get the object which manages field assigners for the current scope. |
342 | 362 |
* |
343 | 363 |
* @return Current scope. |
new/src/com/goldencode/p2j/util/Accumulator.java 2022-09-01 08:54:09 +0000 | ||
---|---|---|
2 | 2 |
** Module : Accumulator.java |
3 | 3 |
** Abstract : Abstract base class for concrete accumulator implementations |
4 | 4 |
** |
5 |
** Copyright (c) 2004-2019, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2004-2022, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- --JPRM-- -----------------------------Description----------------------------- |
8 | 8 |
** 001 ECF 20051227 @23778 Created initial version. Base class for |
... | ... | |
117 | 117 |
** when reset() called without accumulate(). |
118 | 118 |
** 028 CA 20190326 Implemented TransactionHelper instead of direct usage of the static |
119 | 119 |
** API. This allows the elimination of context local usage in TM. |
120 |
** 029 CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
121 |
** registration is now specific to each type of scopeable. For each case, the block |
|
122 |
** will be registered for scope support (for that particular scopeable) only when |
|
123 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
124 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
125 |
** processing all the scopeables for each and every block. |
|
120 | 126 |
*/ |
121 | 127 |
/* |
122 | 128 |
** This program is free software: you can redistribute it and/or modify |
... | ... | |
176 | 182 |
import java.lang.reflect.*; |
177 | 183 |
import java.util.*; |
178 | 184 | |
185 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
186 | ||
179 | 187 |
/** |
180 | 188 |
* Abstract base class for all accumulators. An accumulator collects one |
181 | 189 |
* piece of data upon each pass through an iterative loop and calculates a |
... | ... | |
1099 | 1107 |
{ |
1100 | 1108 |
// no-op |
1101 | 1109 |
} |
1110 |
|
|
1111 |
/** |
|
1112 |
* Get the {@link ScopeId} for the instance. |
|
1113 |
* |
|
1114 |
* @return <code>null</code>, as the scope notification is done via {@link AccumulatorManager}. |
|
1115 |
*/ |
|
1116 |
@Override |
|
1117 |
public ScopeId getScopeId() |
|
1118 |
{ |
|
1119 |
// no ID necessary, as it does not get registered explicitly, is called via AccumulatorManager |
|
1120 |
return null; |
|
1121 |
} |
|
1102 | 1122 | |
1103 | 1123 |
/** |
1104 | 1124 |
* Process a notification that a new block scope has been entered. Each |
new/src/com/goldencode/p2j/util/AccumulatorManager.java 2022-09-01 08:53:49 +0000 | ||
---|---|---|
2 | 2 |
** Module : AccumulatorManager.java |
3 | 3 |
** Abstract : provides block-behavior for the accumulators. |
4 | 4 |
** |
5 |
** Copyright (c) 2008-2021, Golden Code Development Corporation.
|
|
5 |
** Copyright (c) 2008-2022, Golden Code Development Corporation.
|
|
6 | 6 |
** |
7 | 7 |
** -#- -I- --Date-- -T- --JPRM-- ----------------Description----------------- |
8 | 8 |
** 001 CA 20080129 @37024 Created initial version. Provides context |
... | ... | |
33 | 33 |
** 010 CA 20200930 Refactored to remove the singleton scopeable instance (which forced the scope |
34 | 34 |
** notifications to use context-local state). |
35 | 35 |
** CA 20210310 Small performance improvement. |
36 |
** CA 20220901 Refactored scope notification support: ScopeableFactory was removed, and the |
|
37 |
** registration is now specific to each type of scopeable. For each case, the block |
|
38 |
** will be registered for scope support (for that particular scopeable) only when |
|
39 |
** the scopeable is 'active' (i.e. unnamed streams or accumulators are used). This |
|
40 |
** allows a lazy registration of scopeables, to avoid the unnecessary overhead of |
|
41 |
** processing all the scopeables for each and every block. |
|
36 | 42 |
*/ |
37 | 43 |
/* |
38 | 44 |
** This program is free software: you can redistribute it and/or modify |
... | ... | |
91 | 97 | |
92 | 98 |
import java.util.*; |
93 | 99 |
import com.goldencode.p2j.security.ContextLocal; |
100 |
import com.goldencode.p2j.util.Scopeable.ScopeId; |
|
94 | 101 |