0% found this document useful (0 votes)
834 views11 pages

Pat 162007914

The document outlines the creation and application of patch PAT162007914 for Content Server version 16.2.0, aimed at simplifying license audits for performance improvements. It includes instructions for stopping services, backing up, applying the patch, and restarting services. Additionally, it details the implementation of callback functions to manage licensing audits and permissions within the system.

Uploaded by

testcorreo03
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
834 views11 pages

Pat 162007914

The document outlines the creation and application of patch PAT162007914 for Content Server version 16.2.0, aimed at simplifying license audits for performance improvements. It includes instructions for stopping services, backing up, applying the patch, and restarting services. Additionally, it details the implementation of callback functions to manage licensing audits and permissions within the system.

Uploaded by

testcorreo03
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 11

# Patch PAT162007914 created at Tue Sep 24 12:09:36 CEST 2024

#
# Issue: XECMPF-16358
# Module:
# Version: Content Server 16.2.0 64-bit for Windows
# Update: 24.2.0 (2024-03),24.1.0 (2023-12)
#
# Description:
# Simplify License audit (performance)
#
# 1. Stop all Content Server services.
# 2. Make necessary backup before applying the patch.
# 3. Unpack and place this package to <OTHOME>.
# 4. The directory(s) and file(s) listed above are expected to be copied to
<OTHOME> and replace any existing one(s).
# 5. Start all Content Server services.
#
m {'kernel','llpatch','xecmpf'}
o
{'pat00001::AccessBusinessWorkspace',&&xecmpf::Privileges::AccessBusinessWorkspace}
N AccessBusinessWorkspace
f MayExecuteWithAudit
s

function Boolean MayExecuteWithAudit(Object prgCtx, Integer auditType, Integer


auditItem,
Integer subType = .fSubType, Integer factoryType
= .fFactoryType)

// Disable the licensing usage privileges (XECMPF-16358)


Boolean result = TRUE //.MayExecute( prgCtx, subType, factoryType )

if ( result )
.Audit( prgCtx, auditType, auditItem )
end

return result

end

sEND
f __Init
s

function Void __Init()

if ( .fEnabled )

// License Audit changes (XECMPF-16358):


// Disable derived licensing usage privileges for all Extended ECM
products
//$LLIAPI.ObjectFactorySubsystem.RegisterItem( this,
{ .fFactoryType, .fSubType } )

end

end

sEND
o {'pat00001::XecmpfFilterNodesCallback',&&xecmpf::XecmpfFilterNodesCallback}
N XecmpfFilterNodesCallback
f CBFilterNodes
s
/**
* Callback function to apply Extended ECM permissions on the given nodes.
*
* @param dapiCtx
* DAPI context object
* @param nodeRecs
* Array of requested nodes. All nodes for which the given user
has no permission must be removed.
* @param userID
* ID of the user for which the permissions are evaluated
*
* @return Assoc
* .ok : TRUE upon success, FALSE otherwise
* .errMsg : error message if .ok is FALSE, undefined
otherwise
* .apiError : API error object if .ok is FALSE, undefined
otherwise
*/
function Assoc CBFilterNodes(
Object dapiCtx,
RecArray nodeRecs,
Integer userID )

Assoc retVal
Dynamic result
Object prgCtx = dapiCtx.fPrgCtx
String errMsg = Undefined
Dynamic apiError
Assoc cache = undefined
RecArray ancestorRecs
Integer start
Integer polEnabled = 1
Boolean isPolicyEnabled = false
Boolean getPolicyEnabled = false

retVal.ok = true

// Make sure we don't go through this if the input node array is empty or the
current user has system administrative rights

if ( Length( nodeRecs ) > 0 && !dapiCtx.fPrgCtx.USession().HasByPassPerm() )

// *** Policies: Check for Policies ***

result = $OTSAPXECM.Utils.GetPolicyEnabledFlag( prgCtx )


if( result.ok && result.found )
isPolicyEnabled = result.policyEnabled
else
getPolicyEnabled = TRUE
end

if ( getPolicyEnabled )

retVal = $OTSAPXECM.Utils.IsAnyPolicyEnabled( prgCtx )


if ( retval.ok )

isPolicyEnabled = retval.policyEnabled
result = $OTSAPXECM.Utils.PutPolicyEnabledFlag( prgCtx,
isPolicyEnabled )
if( !result.ok )
$OTSAPXECM.LoggingUtils.LogError('policy enabled
register',this,result.errMsg)
end

end

end

if retval.ok && isPolicyEnabled

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


"...starting to check policies." )

// *** continue with "normal" policy checking

if IsFeature( dapiCtx, "fPolicyCache" )


cache = dapiCtx.fPolicyCache
if IsFeature( cache, 'ValidUntilTick' ) && Date.Tick() <=
cache.ValidUntilTick

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


"using cache, still valid for ticks: " + Str.String( cache.ValidUntilTick -
Date.Tick() ) )
else

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


"rebuilding outdated cache" )
cache = undefined
end
else

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


"creating new cache" )
OS.AddFeature( dapiCtx, "fPolicyCache" )
end
if IsUndefined( cache )
cache = Assoc.CreateAssoc( )
cache.ValidUntilTick = Date.Tick() +
CAPI.IniGet( prgCtx.fDbConnect.fLogin, $XECMPF.fIniSectionConfig,
"FilterNodesCallbackCache", 100000 )
dapiCtx.fPolicyCache = cache
end

start = Date.Tick()

result = .GetFilterInfoFromNodeRecs( prgctx,


RecArray.ColumnToList( nodeRecs, "DataID" ) )
result.records
= .RemoveDuplicateParentsFromNodeRecs( result.records )

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


str.format( "timing for joined filter query: %1", Date.Tick() - start ) )

if result.ok
ancestorRecs = result.records

//is any policy enabled


if polEnabled in RecArray.ColumnToList( ancestorRecs,
"WKSP_POL_ENABLED" )

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


str.format( "records prior to filtering: %1", length( nodeRecs ) ) )
result = .FilterItems4Policies( prgCtx, ancestorRecs,
nodeRecs )

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


str.format( "records after filtering: %1", length( nodeRecs ) ) )
else

$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes", this,


"no policy related items found" )
end

else
retVal.ok = false
errMsg = result.errMsg

$OTSAPXECM.LoggingUtils.LogError( "FilterNodesCallBack:CBFilterNodes", this,


"Error applying filter ('GetFilterInfoFromNodeRecs')" )
end
end

// *** END Policies ***/

end

if IsDefined( errMsg )
$OTSAPXECM.LoggingUtils.LogError( "FilterNodesCallBack:CBFilterNodes",
this, errMsg )
retVal.Ok = FALSE
retVal.errMsg = errMsg
retVal.apiError = apiError
$OTSAPXECM.LoggingUtils.LogDebug( "FilterNodesCallBack:CBFilterNodes",
this, "end with error: " + errMsg )
else
retVal.ok = TRUE
end

return retVal

end

sEND
o {'pat00001::XECMPFNodeCallbacks',&&xecmpf::XECMPFNodeCallbacks}
N XECMPFNodeCallbacks
I {'pat00001::BusinessWorkspaceCB','pat00001::XECMPFNodeCallbacks'}
N BusinessWorkspaceCB
f CBListContents
s
/**
* Perform License Audit (old Extended ECM Licensing) if we are opening a business
workspace
* (XECMPF-16358).
*
* This replaces the performance critical License Audit in
XecmpfFilterNodesCallback.
*
* @param {DAPINODE} node
* @param {RecArray} childRecs
* @param {String} viewName
*
* @return {Assoc}
* @returnFeature {Boolean} ok FALSE if an error occurred, TRUE otherwise
* @returnFeature {String} errMsg Error message, if an error occurred
* @returnFeature {Dynamic} apiError Error object, if applicable
*/
function Assoc CBListContents( DAPINODE node, RecArray childRecs, String viewName )

Assoc checkVal
Dynamic apiError
Object dapiCtx
Object prgCtx
String errMsg
RecArray workspaces
Record workspace
Integer nodeID

Boolean ok = TRUE
Boolean skip = TRUE
Boolean enhancedLicensingEnabled = FALSE

// Check for both workspace and workspace volume because


// for workspaces without content this event is only triggered for workspace
volume

if ( IsDefined( node ) && node.pSubType in { $TypeEcmWorkspace,


$TypeEcmWorkspaceVolume } )

skip = FALSE

end

if ( !skip )

checkVal = $LLIAPI.NodeUtil.FindDapiCtx( node )

if ( checkVal.ok != TRUE )

ok = FALSE
errMsg = checkVal.errMsg
apiError = checkVal.apiError

else

dapiCtx = checkVal.DapiCtx
prgCtx = dapiCtx.fPrgCtx

end
if ( ok )

checkVal =
$LLIAPIUTILS.LicenseUtils.GetEnhancedLicenseSetting( prgCtx )

if ( checkVal.ok == TRUE )

enhancedLicensingEnabled = checkVal.enhancedLicenseSetting

else

ok = FALSE
errMsg = checkVal.errMsg
$OTSAPXECM.LoggingUtils.LogError(
"BusinessWorkspaceCB:CBListContents",
this,
"Error retrieving Enhanced License Setting." )

end

end

if ( ok && enhancedLicensingEnabled == FALSE )

nodeID = ( node.pSubType == $TypeEcmWorkspaceVolume ) ?


node.pVolumeID : node.pID

checkVal = ._GetItemsForLicensing( prgCtx, nodeID )

if ( checkVal.ok )

workspaces = checkVal.recs

else

ok = FALSE
errMsg = checkVal.errMsg
$OTSAPXECM.LoggingUtils.LogError(
"BusinessWorkspaceCB:CBListContents",
this,
"Error retrieving items for licensing" )

end

if ( ok )

for workspace in workspaces

// License audit for business application and


workspace type.
// For cross-application workspace all involved
business applications are audited.
// Workspace templates must not be audited.

if ( ._IsNonTemplateNode( prgCtx,
workspace.DataID ) )

if ( workspace.extSysId > 0 )
$XECMPF.AccessBusinessWorkspace.Audit(
prgCtx,
$XECMPF.fLicAuditTypeBusApp,
workspace.extSysId )

end

if ( workspace.wsTypeId > 0 )

$XECMPF.AccessBusinessWorkspace.Audit(
prgCtx,
$XECMPF.fLicAuditTypeWkspType,
workspace.wsTypeId )

end

end

end

end

end

end

if ( IsDefined( errMsg ) && Length( errMsg ) > 0 )

$OTSAPXECM.LoggingUtils.LogError( "BusinessWorkspaceCB:CBListContents",
this, errMsg )
$OTSAPXECM.LoggingUtils.LogDebug(
"BusinessWorkspaceCB:CBListContents",
this,
"ends with error: " + errMsg )

end

return Assoc{ "ok": ok, "errMsg": errMsg, "apiError": apiError }

end

sEND
g _GetItemsForLicensing
s
private function Assoc _GetItemsForLicensing( Object prgCtx, Integer nodeID )

RecArray recs
String q1, q2, q3
String stmt
Dynamic dbResult
String errMsg
Dynamic apiError

Boolean ok = TRUE
Object dbconnect = prgCtx.fDBConnect

// The actual query consists of 3 parts which are accumulated via UNION ALL
statement.

// 1st part selects workspaces with a business object assigned (late


workspaces)
q1 =
"SELECT lk.DATAID AS DataID, " +
" extSys.EXTSYSTEM_NODE_ID AS extSysId, wst.CONFIG_NODE_ID AS wsTypeId
" +
"FROM OTSAPXECM_WKSP_LINKS lk " +
"INNER JOIN OTSAP_BO_TYPES bot ON bot.ID_BO_TYPE = lk.ID_BO_TYPE " +
"INNER JOIN OTSAP_REF_TYPES wst ON wst.ID_REFERENCE_TYPE =
bot.ID_REFERENCE_TYPE " +
"INNER JOIN OTSAP_EXT_SYSTEMS extSys ON extSys.ID_EXTSYSTEM =
bot.ID_EXTSYSTEM " +
"WHERE lk.DATAID = :A1"

// 2nd part selects workspaces without business object type (pure business
workspaces)
q2 =
"SELECT lk.DATAID AS DataID, " +
" 0 AS extSysId, wst.CONFIG_NODE_ID AS wsTypeId " +
"FROM OTSAPXECM_WKSP_NOLINK lk " +
"INNER JOIN OTSAP_REF_TYPES wst ON wst.ID_REFERENCE_TYPE =
lk.ID_REFERENCE_TYPE " +
"WHERE lk.DATAID = :A2"

// 3rd part selects workspaces with business object type but without business
object
// assigned (early workspaces)
q3 =
"SELECT lk.DATAID AS DataID, " +
" extSys.EXTSYSTEM_NODE_ID AS extSysId, wst.CONFIG_NODE_ID AS wsTypeId
" +
"FROM OTSAPXECM_WKSP_NOLINK lk " +
"INNER JOIN OTSAP_REF_TYPES wst ON wst.ID_REFERENCE_TYPE =
lk.ID_REFERENCE_TYPE " +
"INNER JOIN OTSAP_BO_TYPES bot ON bot.ID_REFERENCE_TYPE =
wst.ID_REFERENCE_TYPE " +
"INNER JOIN OTSAP_EXT_SYSTEMS extSys ON extSys.ID_EXTSYSTEM =
bot.ID_EXTSYSTEM " +
"WHERE lk.DATAID = :A3"

stmt = Str.Join( { q1, "UNION ALL", q2, "UNION ALL", q3 }, " " )

dbResult = CAPI.Exec( dbConnect.fConnection, stmt, nodeID, nodeID, nodeID )

if ( IsNotError( dbResult ) )

if ( Length( dbResult ) > 0 )

recs = dbResult

end

else

ok = FALSE
errMsg = 'Error executing SQL query.'
apiError = Error.ErrorToString( dbResult )

end

return Assoc{ "ok": ok, "errMsg": errMsg, "apiError": apiError, "recs":


recs }

end

sEND
g _IsNonTemplateNode
s
private function Boolean _IsNonTemplateNode( Object prgCtx, Integer nodeID )

String stmt
Dynamic result

CAPICONNECT connect = prgCtx.fDBConnect.fConnection


List docTemplCache =
prgCtx.GetSessionProperty( .fDocumentTemplateNodesCacheKey )

if ( IsUndefined ( docTemplCache ) )

docTemplCache = {}
stmt = "SELECT DataID FROM DTreeCore WHERE OwnerID = :A1"
result = CAPI.Exec( connect, stmt, -
$XECMPF.fDocumentTemplatesVolumeID )

if ( !IsError( result ) )

docTemplCache = RecArray.ColumnToList( result, "DataID" )

end

prgCtx.SetSessionProperty( .fDocumentTemplateNodesCacheKey,
docTemplCache )

end

return ( ! ( nodeID in docTemplCache ) )

end

sEND
g fDocumentTemplateNodesCacheKey
v 'XECMPF.DocumentTemplateNodes'
f fEnabled
v true
f fSubTypes
v ?
o {'pat00001::PostPatchActions',&&llpatch::PostPatchActions}
N PostPatchActions
g Action20240918_147100
s
function void Action20240918_147100()

// Unregister all Access Business Workspaces usage privileges


Dynamic items = $LLIAPI.ObjectFactorySubsystem.GetItems()
Dynamic item
Dynamic parent
Integer count = 0
Integer i
Dynamic key

echo("........Going to unregister licensing usage privileges")

for item in items

i = 1
parent = item.OSParent

while IsDefined( parent ) && parent != #0 && i < 10

if( parent.OSName == 'LicensingUsagePrivilege' )

key = { item.fFactoryType, item.fSubType }


$LLIAPI.ObjectFactorySubsystem.UnregisterItem( key )
break

else

parent = parent.OSParent
i += 1

end

end

end

echo("........", count, " privileges successfully unregistered.")

// Register the new BusinessWorkspaceCB callback

Object o
Boolean found = false

echo("........Going to register BusinessWorkspacesCB")

o = XECMPF::XECMPFNodeCallbacks::BusinessWorkspaceCB

if( IsDefined ( o ) )

o.__Init()
found = TRUE

end

/*
for o in
$KERNEL.OSpaceUtils.ChildrenByOSpace(XECMPF::XECMPFNodeCallbacks::BusinessWorkspace
CB)
if( o.OSName == "BusinessWorkspaceCB" )
found = true
echo( "........BusinessWorkspaceCB found." )
o.__Init()
echo( "........BusinessWorkspaceCB initialized." )
break
end
end
*/

if( found )
echo("........Action successfully finished.")
else
EchoError("XECMPF::XECMPFNodeCallbacks::BusinessWorkspaceCB not
found.")
end

end
sEND

You might also like