Source code for adapya.entirex.cmdinfo

#! /usr/bin/env python
# -*- coding: latin1 -*-

"""cmdinfo.py interface to Webmethods EntireX Broker CIS Services
and service explorer

Only a selection of the available fields is shown (see _FIELDS)

This covers the Broker API for Command and Information Services V9.7

Usage: cmdinfo [options]

Options::

    -h, --help              display this help
    -b, --broker ..         id of broker ETBxxxxx or hostname:port

    -c, --class ..          Broker server class (selector)
    -d  --detail            info request detailed conversation/uows
    -n, --name ..           Broker server name (selector)
    -k, --token ..          Token
    -m, --maxinfo ..        Receive buffer length - default 32768
    -o, --option ..         Option: QUIESCE, IMMED (first char suffices)
    -p, --puid              Physical user id (selector)
    -q, --seqno <int>       Sequence number (selector)
    -s, --service ..        Broker service (selector)
                              short: -s class/server/service
    -i, --infouid ..        user id for broker communication
    -u, --userid ..         user id for information on active clients (selector)
    -v, --convid ..         conversation id (selector)
    -w, --uowid ..          unit of work (selector)
    -x, --password ..       password
    -t, --trace ..          sum of trace flags
                            1 - dump buffers before Broker call
                            2 -              after call
                            4 - print broker calls, short and data
                            8 - detailed print of buffers

    CIS commands (default command: info)

    -S, --shutdown          needs parameters convid or service or seqno (for server)
                             or userid/puid/token for client
    -P, --purge <uowid>     psf remove uow from persistent store
    -T, --btrace <level>    Broker trace on level 1-8, 0 switch off


Example::

    1. show all services for broker class REPTOR and server MMSERV
       and related conversations, units of work and servers;
       show clients starting with userid MM
       show general broker information first::

         > cmdinfo -b zos3:3800 -u MM -s REPTOR/MMSERV/*

    2. shutdown a participant identified by userid, service and/or conversation::

         > cmdinfo -b zos3:3800 -Su OUT4_Reader
                                -Ss REPTOR/MMSERV/OUT4
                                -Sv 1290000000000105

"""
from __future__ import print_function          # PY3

from adapya.base.defs import Abuf
from adapya.base.dump import dump
from adapya.base.datamap import Datamap, String, Bytes, Filler, Uint1, \
    Uint2, Uint4, Uint8, T_HEX, T_IN, T_OUT, T_INOUT, T_NONE, str_str
from adapya.base.dtconv import intervalstr
from adapya.entirex.broker import Broker, BrokerException
from time import localtime, strftime

cis_version=10
# try this Broker version where Info_* classes in etbcinf.py can be used
# initial communication with Broker the kernel version determines if
# the classes need to be imported from etcinf8.py


[docs]class CISError(BrokerException): """Example use: try: info = cis.iget(...) except CISError as e: if e.epa.cishdr.error_code == x: print('\nCIS error: %s on %s/%s/%s' %(e.value, sv.server_class,sv.server,sv.service)) """ def __init__(self, value, epa): self.value = value self.epa = epa def __str__(self): return repr(self.value)
stckintervalstr = lambda i: intervalstr(int(i / 1.048576)) localtime_str = lambda t: strftime("%Y-%m-%d %H:%M:%S",localtime(t)) def usage(): print(__doc__) # --- EntireX Broker CIS Objects Constants ---------------------------- # * = no further selection crit. needed CIO_BROKER = 7 #* CIO_CLIENT = 2 # active clients CIO_CMDLOG_FILTER = 23 # CIO_CONVERSATION = 4 # active conversations CIO_NET = 24 #* (INF) NET-WORK CIO_PARTICIPANT = 18 # CIO_POOL_USAGE = 25 #* (INF) pool usage and dynam. memory management CIO_PSF = 9 # (INF) unit of work status CIO_PSFADA = 12 #* (INF) Adabas persistent store CIO_PSFCTREE = 20 #* (INF) c-tree persistent store CIO_PSFDIV = 11 #* (INF) DIV persistent store CIO_PSFFILE = 13 #* (INF) (deprecated) CIO_PSFMSG = 10 # (INF) CIO_PUBLICATION = 16 # (INF) active publications (deprecated) CIO_PUBLISHER = 15 # (INF) active publishers (deprecated) CIO_RESOURCE_USAGE = 26 #* (INF) Broker resource usage CIO_SECURITY = 21 #* CIO_SERVER = 1 # active servers CIO_SERVICE = 6 # active services CIO_SSL = 22 #* SSL communication CIO_STATISTICS = 27 #* (INF) stats on Broker resources CIO_SUBSCRIBER = 14 # (deprecated) CIO_TCP = 19 #* (INF) TCP communications CIO_TRANSPORT = 29 # (CMD) CIO_TOPIC = 17 # (INF) active topics (deprecated) CIO_UOW_STATISTICS = 31 # (INF) stats on Broker resources CIO_USER = 28 # (INF) Info on all users CIO_WORKER = 8 # (INF) Info on all workers CIO_WORKER_USAGE = 8 #* (INF) Info on all workers cio_str = lambda i: str_str(i, {7:'BROKER',2:'CLIENT',23: 'CMDLOG_FILTER', 4:'CONVERSATION',24:'NET',18:'PARTICIPANT', 25:'POOL_USAGE', 9:'PSF', 12:'PSFADA', 20:'PSFCTREE', 11:'PSFDIV', 16:'PUBLICATION', 15:'PUBLISHER', 26:'RESOURC_USAGE', 21:'SECURITY',1:'SERVER',6:'SERVICE',22:'SSL',27:'STATISTICS', 14:'SUBSCRIBER',19:'TCP', 29:'TRANSPORT', 17:'TOPIC', 31:'UOW_STATISTICS', 28:'USER', 8:'WORKER', 8:'WORKER_USAGE'}) # --- EntireX Broker CIS Commands Constants ---------------------------- CIC_ALLOW_NEWUOWMSGS = 13 CIC_CLEAR_CMDLOG_FILTER = 20 CIC_CONNECT_PSTORE = 17 CIC_DISABLE_ACCOUNTING = 28 CIC_DISABLE_CMDLOG = 24 CIC_DISABLE_CMDLOG_FILTER = 22 CIC_DISABLE_DYN_WORKER = 37 CIC_DISCONNECT_PSTORE = 18 CIC_DISPLAY_REQUESTS = 45 # display number of requests CIC_ENABLE_ACCOUNTING = 27 CIC_ENABLE_CMDLOG = 23 CIC_ENABLE_CMDLOG_FILTER = 21 CIC_ENABLE_DYN_WORKER = 38 CIC_FORBID_NEWUOWMSGS = 14 CIC_NO_OPERATION = 88 CIC_PRODUCE_STATISTICS = 25 CIC_PURGE = 12 CIC_RESET_USER = 29 CIC_RESUME = 31 CIC_SET_CMDLOG_FILTER = 19 CIC_SET_SINGLE_CONVERSATION = 40 # requires interface V8 CIC_SET_UOW_STATUS = 42 # requires V10 CIC_SHUTDOWN = 8 CIC_START = 33 CIC_STATUS = 36 CIC_STOP = 32 CIC_SUBSCRIBE = 15 # deprecated CIC_SUSPEND = 30 CIC_SWITCH_CMDLOG = 26 CIC_TRACE_FLUSH = 35 CIC_TRACE_OFF = 2 CIC_TRACE_ON = 1 CIC_TRAP_ERROR = 34 CIC_UNSUBSCRIBE = 16 # deprecated cic_str = lambda i: str_str(i, { 13:'ALLOW_NEWUOWMSGS',20:'CLEAR_CMDLOG_FILTER',17:'CONNECT_PSTORE', 28:'DISABLE_ACCOUNTING',24:'DISABLE_CMDLOG',22:'DISABLE_CMDLOG_FILTER', 37:'DISABLE_DYN_WORKER',18:'DISCONNECT_PSTORE',27:'ENABLE_ACCOUNTING', 23:'ENABLE_CMDLOG',21:'ENABLE_CMDLOG_FILTER',38:'ENABLE_DYN_WORKER', 14:'FORBID_NEWUOWMSGS',88:'NO_OPERATION',25:'PRODUCE_STATISTICS', 12:'PURGE',29:'RESET_USER',31:'RESUME',19:'SET_CMDLOG_FILTER', 8:'SHUTDOWN',33:'START',36:'STATUS',32:'STOP',15:'SUBSCRIBE', 30:'SUSPEND',26:'SWITCH_CMDLOG',35:'TRACE_FLUSH',2:'TRACE_OFF', 1:'TRACE_ON',34:'TRAP_ERROR',16:'UNSUBSCRIBE'} ) # --- EntireX Broker CIS Options Constants ---------------------------- CIP_IMMED = 3 CIP_QUIESCE = 4 CIP_TR_LEVEL1 = 11 CIP_TR_LEVEL2 = 12 CIP_TR_LEVEL3 = 13 CIP_TR_LEVEL4 = 14 CIP_TR_LEVEL5 = 15 CIP_TR_LEVEL6 = 16 CIP_TR_LEVEL7 = 17 CIP_TR_LEVEL8 = 18 CIP_UOW_STATUS_ACCEPTED = 20 CIP_UOW_STATUS_CANCELLED = 21 CIP_ETB_FORCE = 26 # Forced operation CIP_ETB_PREFETCH = 27 # ARF: OPTION PREFETCH cip_str = lambda i: str_str(i, { 3:'CIP_IMMED', 4:'QUIESCE', 11:'TR_LEVEL1', 12:'TR_LEVEL2',13:'TR_LEVEL3',14:'TR_LEVEL4',15:'TR_LEVEL5', 16:'TR_LEVEL6',17:'TR_LEVEL7',18:'TR_LEVEL8', 20:'UOW_STATUS_ACCEPTED', 21:'UOW_STATUS_CANCELLED', 26:'ETB_FORCE', 27:'ETB_PREFETCH' } ) # Broker Information service Error Codes bis_error = lambda i: str_str(i, { 0:'Successful response', 1:'Invalid block length', 2:'Invalid VERSION', 3:'OBJECT-TYPE missing', 4:'Nothing found for this request', 5:'Invalid OBJECT-TYPE', 6:'Invalid Info Level', 7:'Block length too short for Object Type', 8:'User selection must be unique', 9:'Service selection must be unique', 10:'Topic name must be specified (deprecated)', 11:'PUID not possible with Info Level SHORT', }) # Broker command service Error Codes bcs_error = lambda i: str_str(i, { 0:'Successful response', 2:'Invalid VERSION', 3:'OBJECT-TYPE is missing', 5:'Invalid OBJECT-TYPE', 20:'The user is not authorized to issue Broker commands', 21:'Invalid COMMAND', 22:'Invalid OPTION', 23:'Shutdown possible for servers only', 24:'Participant not found', 25:'Purge UOW failed', 26:'User specification must be unique', 27:'Topic name must be specified (deprecated)', 28:'Add subscription failed (deprecated)', 29:'Remove subscription failed (deprecated)', 30:'User must be specified', 31:'Class/Server/Service must be unique', 32:'Class and Topic cannot both be specified (deprecated)', 33:'Class, Topic or User must be specified', 34:'Set command log filter failed', 35:'Clear command log filter failed', 36:'Enable command log filter failed', 37:'Disable command log filter failed', 38:'Switch command log files failed', 39:'Set security trace level failed', 40:'Set PSTORE (PSF) trace level failed', 41:'Enable command logging failed', 42:'Disable command logging failed', 43:'Connect PSTORE failed', 44:'Disconnect PSTORE failed', 45:'Allow new UOW messages failed', 46:'Forbid new UOW messages failed', 47:'Enable accounting failed', 48:'Disable accounting failed', 49:'Reset user failed', 50:'Command refused in current RUN-MODE', 51:'Service must be specified', 52:'Service not found', 53:'CONVID must be specified', 54:'Conversation not found', 55:'Cannot inhibit Conversation', 56:'Only supported for messages', 57:'Cannot lock Conversation', 58:'Not for currently running Conversation', 59:'Security violation detected', 60:'Invalid transport ID', 61:'Cannot execute command', 62:'Command ignored. Only one Communicator left', 63:'Command ignored. Cannot stop all Communicators', 64:'Communicator currently not suspended', 65:'Communicator currently not stopped', 66:'Communicator currently not active', 67:'Enable Dynamic Worker Management failed', 68:'Disable Dynamic Worker Management failed', 69:'Transport reserved for Broker Service', 70:'TRACE-FLUSH failed', 71:'Cannot set single-conversation mode because service is being used in other mode'\ ' (still active conversations for service)', 72:'Verification of attribute file failed', 73:'Cannot delete deferred service with UOW', 74:'Cannot set UOW status', 75:'Cannot add service to SCM record', 76:'Update SCM record failed', 77:'Conversation contains unprocessed UOWs', }) # --- EntireX Broker Command Request Structure ------------------------
[docs]class Cisreq(Datamap): def __init__(self, **kw): fields=( # Available with CIS Interface version Uint2('version', opt=T_IN), # 1 Interface version Uint2('object_type', opt=T_IN, ppfunc=cio_str), # 1 Object type to which the command applies Uint2('command', opt=T_IN, ppfunc=cic_str), # 1 CIS command Uint2('option', opt=T_IN, ppfunc=cip_str), # 1 CIS option Bytes('puid', 28,opt=T_HEX),# 1 internal userid that distinguishes users with same userids # id obtained from previous call, no translation done String('uowid', 16,opt=T_IN), # 2 Selector, optional, unit of work to be purged String('topic', 96,opt=T_IN), # 4 Selector, optional, topic to be subscribed or unsubscribed to String('uid', 32,opt=T_IN), # 4 Selector, optional, user name for subscription/unsubscription # and participant shutdown String('token', 32,opt=T_IN), # 4 Selector, optional, token for subscription/unsubscription # and participant shutdown String('server_class',32,opt=T_IN), # 5 Selector, optional, for command log filter addition or removal String('server', 32,opt=T_IN), # 5 Selector, optional, for command log filter addition or removal String('service', 32,opt=T_IN), # 5 Selector, optional, for command log filter addition or removal Filler('reserved', 32), # 5 Reserved String('conv_id', 16,opt=T_IN), # 7 Selector, optional, for shutdown conversation String('transportid', 3,opt=T_IN), # 7 Selector, optional, for transport task (NET|Snn|Tnn) # required for RESUME,START,STATUS,STOP,SUSPEND Uint1('exclude_attach', opt=T_IN), # 7 Optional. Exclude attach servers when shutting down a service Uint4('seqno', opt=T_IN), # 7 Optional. Sequence number of participant (e.g. client, server, # publisher) to be shut down. Can be used instead of puid Uint4('error_number', opt=T_IN), # 7 Optional. Sequence number of participant (e.g. client, server, ) Datamap.__init__(self, 'Cisreq', *fields, **kw)
[docs] def reset(self,v=cis_version): """ Reset values of the CIS Request instance """ self.update( version=v, # interface level 8 # init alpha selection fields with blanks conv_id='', seqno=0, server_class='', server='', service='', token='', topic='', transportid='', uid='', uowid='', )
errinf_str = lambda i: str_str(i, { 0:'OK',1:'Invalid block length',2:'Invalid API version', 3:'Object Type missing',4:'Nothing found for this request', 5:'Invalid Object Type',6:'Invalid Info Level', 7:'Block length too short for Obj. Type',8:'User selection must be unique', 9:'Service selection must be unique',10: 'Topic name must be specified', }) # --- EntireX Broker CIS Response Header ------------------------------ # (Struct HD_CIS). Common header used by information services and # the command service. # The header structure is always the first structure # in the receive buffer that comes back from an information # or command service request. Even receive buffers obtained # with subsequent RECEIVE commands have this structure as the # first part of the buffer.
[docs]class Cishdr(Datamap): def __init__(self, **kw): fields=( Uint4('error_code'), # 1 CIS return code (0 = OK) Uint4('totobj'), # 1 Total number of objects returned in object list Uint4('curobj'), # 1 Number of objects returned within current receive block Uint4('max_sc_len'), # 1 longest SERVER-CLASS value in object list Uint4('max_sn_len'), # 1 longest SERVER-NAME value in object list Uint4('max_sv_len'), # 1 longest SERVICE value in object list Uint4('max_uid_len'), # 1 longest USER-ID value in object list Uint4('max_tk_len'), # 1 longest TOKEN value in object list Uint4('max_topic_len'), # 4 longest TOPIC value in object list Uint4('requesttime',ppfunc=localtime_str),# 4 time that request was received by broker kernel Uint4('reserved',opt=T_NONE), # 4 String('etb_error_code',8), # 5 Secondary error code from broker kernel String('etb_error_text',40), # 5 Secondary error text from broker kernel Uint4('max_ppc_lib_len'), # 6 longest RPC-LIB value in object list Uint4('max_ppc_pgm_len'), # 6 longest RPC-PGM value in object list ) Datamap.__init__(self, 'Cishdr', *fields, **kw)
# --- EntireX Broker Information Request Structure ------------------------
[docs]class Infreq(Datamap): """ Information request Structure Class """ def __init__(self, **kw): fields=( # Available with CIS Interface version # | Optional/Required # | | Uint4('block_length'), # 1 R Return data in this length Uint2('version'), # 1 R Interface version Uint2('reserved1',opt=T_NONE), # Uint2('object_type'), # 1 R Object type for which info is requested String('uid', 32), # 1 O Selector user id of client or server Bytes('puid', 28,opt=T_HEX), # 1 O Selector internal userid that distinguishes users # with same userids, no translation done String('token', 32), # 1 O Selector String('server_class', 32), # 1 O Selector String('server', 32), # 1 O Selector String('service', 32), # 1 O Selector String('conv_id', 16), # 1 O Selector Uint2('reserved2',opt=T_NONE), # 1 String('uowid', 16), # 2 O Selector Uint1('uowstatus'), # 2 O Selector String('userstatus', 32), # 2 O Selector String('recvuid', 32), # 2 O Selector UOW reciever's user id String('recvtoken', 32), # 2 O Selector UOW reciever's token String('recvserver', 32), # 2 O Selector UOW reciever's server name String('recvservice', 32), # 2 O Selector UOW reciever's service name String('recvclass', 32), # 2 O Selector UOW reciever's class name String('reserved3', 3,opt=T_NONE), # 2 String('topic', 96), # 4 O Selector String('publicationid', 16), # 4 O Selector Uint2('subscriptiontype'), # 4 O Selector Uint2('reserved4',opt=T_NONE), # 4 Uint2('conv_type'), # 5 O Selector Uint2('reserved5',opt=T_NONE), # 5 ) Datamap.__init__(self, 'Infreq', *fields, **kw)
[docs] def reset(self,v=cis_version): """ reset values of the Information Request instance """ self.update( version=v, # interface level 9 (UOW statistics) # init alpha selection fields with blanks uid='', token='', server_class='', server='', service='', conv_id='', uowid='', userstatus='', recvuid='', recvtoken='', recvserver='', recvservice='', recvclass='', topic='', publicationid='', )
class Cis(object): def __init__(self, cis='INFO', broker='', user='', trace=0, rcvsize=32768): """ Command and Information service object cis = default 'INFO' - full information on all clients/servers/conversations 'CMD' - command services 'USER-INFO' - Information limited to user's own resources 'PARTICIPANT-SHUTDOWN' 'SECURITY-CMD' """ global cis_version self.rcvsize=rcvsize self.bb = Broker() self.bb.trace = trace & 7 #bb.trace=1 # dump buffers before Broker calls #bb.trace=2 # dump buffers after Broker calls # bb.trace=4 # print Broker calls # bb.trace=6 # print Broker calls + dump buffers after self.bb.broker_id = broker self.bb.user_id = user self.trace = trace # set CIS fixed service names self.bb.server_class= 'SAG' self.bb.server_name = 'ETBCIS' self.bb.service = cis # type of CIS service (INFO, CMD, ..) # set up CIS structures: request and info buffer self.cishdr=Cishdr() # cis header in receive / info buffer self.bb.receive_buffer = Abuf(rcvsize) self.bb.receive_length = rcvsize self.cishdr.buffer=self.bb.receive_buffer if cis == 'INFO': self.infreq=Infreq() self.infreq.buffer=Abuf(self.infreq.dmlen) self.infreq.reset() # reset search fields self.infreq.block_length=rcvsize-self.cishdr.dmlen # size of usable info buffer self.bb.send_buffer=self.infreq.buffer self.bb.send_length=self.infreq.dmlen elif cis in ('CMD', 'PARTICIPANT-SHUTDOWN', 'SECURITY-CMD'): self.req=Cisreq() self.req.buffer=Abuf(self.req.dmlen) self.req.reset(v=cis_version) # reset optional fields self.bb.send_buffer=self.req.buffer self.bb.send_length=self.req.dmlen else: print('Unsupported request', cis) print('Terminating') exit(1) def __enter__(self): # context manager global cis_version print('\n%s' % self.bb.version()) kernel_version = self.bb.kernelVersion() print('\nKernel %s \n with kernelsecurity=%s' % ( kernel_version, self.bb.kernelsecurity)) # extract major version number: "Version 9.12.0.1" _, v2 = kernel_version.split(' ',1) # maxsplit=1 in PY3 major, _ = v2.split('.',1) # maxsplit=1 in PY3 kv = int(major) if kv < 10: cis_version = 8 # bb.kernelsecurity=KERNEL_SECURITY_NO this is set by kernelVersion() # when using ACI level 8 or higher self.bb.logon() # L O G O N # print('Kernel Version=%s' % bb.kernelVersion()) # print('server_class=%s\nserver_name=%s\nservice=%s'% \ # (self.bb.server_class, self.bb.server_name, self.bb.service)) print('\nStarted CIS Session with Broker %s' % self.bb.broker_id) return self def __exit__(self, type, value, tb): # context manager self.bb.logoff() print('Logged off from CIS Session with Broker') def icmd(self, obj, cmd, option=0,conv_id='',puid='',seqno=0, server_class='',server='',service='',token='',uid='',uowid=''): """ send command request to Broker Example: Perform CIS Command >> with Cis(cis='CMD',broker='da3f:3800',user='MM') as cis: >> ibr = cis.icmd(?) >> ibr.dprint() >> """ self.req.update( object_type=obj, command=cmd, option=option, conv_id=conv_id, # selection server_class=server_class, # selection server=server, # selection service=service, # selection puid=puid, # selection seqno=seqno, token=token, # selection uid=uid, # selection uowid=uowid, # selection ) try: self.bb.conv_id='NONE' # required self.bb.wait='YES' # 0s -> 00200031 if cmd == CIC_SET_SINGLE_CONVERSATION: # needed for other commands that operate on objects of calling user ? self.bb.token=token # also set it in etbcb self.bb.send() if self.trace & 8: print('after cmd execution call to %s/%s/%s' % ( self.bb.server_class, self.bb.server_name, self.bb.service)) self.req.dprint() self.cishdr.dprint() except: if self.trace&8: self.req.dprint() self.cishdr.dprint() self.bb.dprint() raise CISError('Error during processing CIS command',self) finally: if self.cishdr.error_code > 0: ec = self.cishdr.error_code raise CISError('Broker Command Service Error %d: %s' % ( ec, bcs_error(ec)), self) def iget(self, itype, uid='', puid='', server_class='', server='',service='', token='',conv_id=''): """ function to get one info object Example: get and print general BROKER information >> with Cis(broker='da3f:3800',user='MM') as cis: >> ibr = cis.iget(CIO_BROKER) >> ibr.dprint() >> """ global cis_version if cis_version > 8: from adapya.entirex.etbcinf import Info_broker, Info_UOW_statistics else: from adapya.entirex.etbcinf8 import Info_broker, Info_UOW_statistics # info objects returning only one item - suitable for iget() infos = {CIO_BROKER: Info_broker, CIO_UOW_STATISTICS: Info_UOW_statistics} # currently limited Infoclass = infos.get(itype,None) if Infoclass: self.infreq.object_type = itype # set object type in request info = Infoclass() else: raise CISError('Invalid CIS object for ireader() type %s' % cio_str(itype),self) self.infreq.update( version=9 if itype == CIO_UOW_STATISTICS else cis_version, server_class=server_class, # selection server=server, # selection service=service, # selection uid=uid, # selection puid=puid, # selection token=token, # selection conv_id=conv_id, # selection ) try: self.bb.conv_id='NEW' self.bb.wait='YES' # 0s -> 00200031 self.bb.send() if self.trace & 8: print('after first call') self.infreq.dprint() self.cishdr.dprint() if self.cishdr.error_code == 4: info = None elif self.cishdr.error_code > 0: ec = self.cishdr.error_code raise CISError('Broker Information Service Error %d: %s' % ( ec, bis_error(ec)), self) else: # self.cishdr.error_code == 0 if self.cishdr.totobj != 1: raise CISError('Nothing returned from Broker CIS',self) offset=self.cishdr.dmlen # first info after cishdr info.buffer=Abuf(info.dmlen) info.buffer.value=self.bb.receive_buffer[offset:offset+info.dmlen] self.bb.endConversation() return info except: raise # return any error def iread(self, itype, uid='', puid='', token='', server_class='', server='',service='', conv_id='',uowid='',uowstatus=0,userstatus='', recvuid='',recvtoken='',recvclass='',recvserver='',recvservice='', topic='',publicationid='', conv_type=0,subscriptiontype=0): """ generator returning info objects from class Example: read and print information on all services of REPTOR server_class >> cis=Cis(broker='da3f:3800',user='MM') >> for iob in cis.iread(CIO_SERVICE,server_class='REPTOR'): >> iob.dprint() >> """ global cis_version if cis_version > 8: from adapya.entirex.etbcinf import Info_conversation, \ Info_client, Info_server, Info_psf, Info_service, Info_UOW_statistics else: from adapya.entirex.etbcinf8 import Info_conversation, \ Info_client, Info_server, Info_psf, Info_service, Info_UOW_statistics ii = Broker() # establish unique conversation for read sequence # copy properties from own Cis object ii.trace = self.bb.trace ii.broker_id = self.bb.broker_id ii.user_id = self.bb.user_id # set CIS fixed service names ii.server_class = 'SAG' ii.server_name = 'ETBCIS' ii.service = 'INFO' # Full information on all clients/servers/conversations cishdr=Cishdr() # cis header in receive / info buffer infreq=Infreq() infreq.buffer=Abuf(infreq.dmlen) infreq.block_length=self.rcvsize-cishdr.dmlen # size of usable info buffer infreq.version=cis_version # interface level 8 # init alpha selection fields from call parameters infreq.uid=uid infreq.puid=puid infreq.token=token infreq.server_class=server_class infreq.server=server infreq.service=service infreq.conv_id=conv_id infreq.uowid=uowid infreq.userstatus=userstatus infreq.recvuid=recvuid infreq.recvtoken=recvtoken infreq.recvserver=recvserver infreq.recvservice=recvservice infreq.recvclass=recvclass infreq.topic=topic infreq.publicationid=publicationid infreq.subscriptiontype=subscriptiontype infreq.conv_type=conv_type ii.receive_buffer=Abuf(self.rcvsize) ii.receive_length = self.rcvsize cishdr.buffer=ii.receive_buffer ii.send_buffer=infreq.buffer ii.send_length=infreq.dmlen infos = {CIO_CLIENT: Info_client, CIO_SERVER: Info_server, CIO_CONVERSATION: Info_conversation, CIO_PSF: Info_psf, CIO_SERVICE: Info_service, CIO_UOW_STATISTICS: Info_UOW_statistics } Infoclass = infos.get(itype,None) if Infoclass: infreq.object_type = itype # set object type in request info = Infoclass() else: raise 'Invalid CIS object for ireader() type %s' % cio_str(itype) try: ii.conv_id='NEW' ii.wait='YES' # 0s -> 00200031 ii.send() if self.trace & 8: print('after first call') infreq.dprint() cishdr.dprint() if self.cishdr.error_code == 4: # 4 nothing found ec = self.cishdr.etb_error_code et = self.cishdr.etb_error_text if not ec == '00000000': print('Broker Information Service ETB Error %d: %s\nNo objects returned' % ( ec, et)) elif self.cishdr.error_code > 0: # print any other error ec = self.cishdr.error_code raise CISError('Broker Information Service Error %d: %s' % ( ec, bis_error(ec)), self) if cishdr.totobj == 0: # raise StopIteration return remaining = cishdr.totobj while 1: offset=cishdr.dmlen # first info after cishdr for i in range(cishdr.curobj): # print('returning %d. object in current' % (i) # info.dprint() info.buffer=Abuf(info.dmlen) info.buffer.value=ii.receive_buffer[offset:offset+info.dmlen] yield info offset += info.dmlen # next offset in receive buffer remaining -= cishdr.curobj if remaining > 0: ii.receive() if self.trace & 8: print('after next call') infreq.dprint() cishdr.dprint() else: # raise StopIteration return except: raise # return with StopIteration or any other error finally: if cishdr.totobj > 0: ii.endConversation() if __name__=='__main__': import getopt import sys from collections import defaultdict, Counter cmd=0 # CIC_ command option=0 # CIP_IMMED /CIP_QUIESCE # CIP_ option obj=0 # CIO_ object puid='' pwd=None brokerid = 'da3f:3800' btrace=0 bservice=bclass=bname='' detail=0 maxinfo=32768 convid='' seqno=0 uowid='' token='' iserv='INFO' # CIS SERVICE buser='cmdinfo.py' # for communication with broker uid='' # for getting information on broker clients try: opts, args = getopt.getopt(sys.argv[1:], 'hb:c:di:k:m:n:o:p:q:P:s:St:T:u:v:w:', ['help','broker=','btrace=','class=','convid=','detail','infouid=', 'name=','option=','password=','puid=','purge=','maxinfo=', 'seqno=','service=','shutdown','shutserv', 'uowid=','userid=','token=','trace=']) except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ('-h', '--help'): usage() sys.exit() elif opt in ('-b', '--broker'): brokerid = arg elif opt in ('-c', '--class'): bclass=arg elif opt in ('-d', '--detail'): detail = 1 # detailed info with conversations and uows elif opt in ('-n', '--name'): bname=arg elif opt in ('-o', '--option'): if arg.upper().startswith('Q'): option=CIP_QUIESCE elif arg.upper().startswith('I'): option=CIP_IMMED elif opt in ('-x', '--password'): pwd=arg elif opt in ('-p', '--puid'): puid=arg elif opt in ('-P', '--purge'): cmd=CIC_PURGE uowid = arg elif opt in ('-m', '--maxinfo'): maxout=int(arg) elif opt in ('-q', '--seqno'): seqno=int(arg) elif opt in ('-s', '--service'): sss=arg.split('/') # --service class:server:service del sss[3:] # skip any extranous items bservice=sss.pop() if sss: bname=sss.pop() if sss: bclass=sss.pop() elif opt in ('-S', '--shutdown'): cmd=CIC_SHUTDOWN elif opt in ('-T', '--btrace'): tlevel=int(arg) if tlevel > 8: tlevel=8 if tlevel > 0: cmd=CIC_TRACE_ON option = CIP_TR_LEVEL1 - 1 + tlevel else: cmd=CIC_TRACE_OFF elif opt in ('-i', '--infouid'): buser=arg elif opt in ('-u', '--userid'): uid=arg elif opt in ('-v', '--convid'): convid=arg detail = 1 elif opt in ('-w', '--uowid'): uowid=arg detail = 1 elif opt in ('-k', '--token'): token=arg elif opt in ('-t', '--trace'): btrace=int(arg) print(80*'=') if cmd == CIC_SHUTDOWN: if convid: obj = CIO_CONVERSATION iserv = 'CMD' print('\nBroker CIS command SHUTDOWN for CONVERSATION %s' % convid) elif seqno or puid: obj = CIO_SERVER iserv = 'CMD' print('\nBroker CIS command SHUTDOWN for server seqno=%d/puid=%s' % (seqno,puid)) elif bservice: obj = CIO_SERVICE iserv = 'CMD' print('\nBroker CIS command SHUTDOWN for service %s/%s/%s' % (bclass,bname,bservice)) elif uid: obj = CIO_PARTICIPANT iserv = 'PARTICIPANT-SHUTDOWN' print('\nBroker CIS command SHUTDOWN for participant %s/%s/%d' % (uid,token,seqno)) else: print('\nBroker CIS command client only supports SHUTDOWN with CONVERSATIONID or SERVICE or participant userid or server seqno') exit(1) elif cmd == CIC_PURGE: if uowid: obj = CIO_PSF iserv = 'CMD' print('\nBroker CIS command PURGE unit-of-work %s' % uowid) else: print('\nBroker CIS command PURGE needs UOWID') exit(1) elif cmd == CIC_TRACE_ON: obj = CIO_BROKER iserv = 'CMD' print('\nBroker CIS command TRACE-ON %d' % tlevel) elif cmd == CIC_TRACE_OFF: obj = CIO_BROKER iserv = 'CMD' print('\nBroker CIS command TRACE-OFF') if cmd > 0: # all comands are processed here with Cis(cis=iserv,broker=brokerid,user=buser,trace=btrace) as cis: ibr = cis.icmd(obj, cmd, option=option, uowid=uowid,conv_id=convid,seqno=seqno, server=bname,service=bservice,server_class=bclass,token=token,uid=uid,puid=puid) exit() # else: (not a command) # use information services # select fields for display of info structures BROKER_FIELDS=('runtime','maxmsgsize','platformname','product_version', 'pstoretype','pstore','uwtime','client_nonact',) SERVICE_FIELDS=('service','conv_nonact','servers_act','conv_act','uwtime', 'totaluows','store','deferrred', 'arf','scm','prefetch','maxPostponeAttempts','postponeDelay' ) # 10 CONV_FIELDS=('conv_id','service','conv_nonact', 'serveruid','servertoken','clientuid','clienttoken','conv_nonact', 'last_active','totaluows', 'arf','scm','prefetch','roaming') # 10: prefetch / roaming ??? PSF_FIELDS=('uow_id','uowstatus','uwcreate_time','uw_lifetime','eoc','deliveries', 'msgcnt','msgsize', 'arf','scm', # 10 line too long: 'maxPostponeAttempts','remainingPostponeAttempts','postponeDelay','back2accepted', 'commit_time') # 10 create_time = Pstore V5?? CS_FIELDS=('uid','puid','puidTrans','token','status','waitconvid','service','conv_act', 'service_act','last_active','nonact','waits_new','waits_old', 'convs','active_uow','recv_option','created','seqno', 'arf','scm','prefetch','roaming') # 10: prefetch / roaming ??? svcs_client = defaultdict(list) conv_client = Counter() uows_client = Counter() with Cis( broker=brokerid,user=buser,trace=btrace) as cis: ibr = cis.iget(CIO_BROKER) ibr.dprint(selectfields=BROKER_FIELDS) for sv in cis.iread(CIO_SERVICE, server_class=bclass, server=bname,service=bservice): # Service selectors: puid or uid/token or uid or token # class/server/service print(80*'-') sv.dprint(selectfields=SERVICE_FIELDS) for sr in cis.iread(CIO_SERVER, server=sv.server, server_class=sv.server_class, service=sv.service): # possible selectors: puid or uid/token or uid or token # class/server/service sr.dprint(selectfields=CS_FIELDS) css='' uidtok='' if detail: for j, cv in enumerate( # Conversation selectors: puid or uid/token or uid or token # class/server/service or conv_id cis.iread(CIO_CONVERSATION, server=sv.server, server_class=sv.server_class, service=sv.service) ): print('Conversation %d'%(j+1)) cv.dprint(selectfields=CONV_FIELDS) if not css: css = '%s/%s/%s' % (cv.server_class,cv.server,cv.service) uidtok = (cv.clientuid,cv.clienttoken) svcs_client[uidtok].append(css) # note all services client uses conv_client[uidtok] += 1 # count all conversations client has uows_client[uidtok] += cv.totaluows # count all uows client has if cv.totaluows > 0: print('Persistent messages for conversation %s' % cv.conv_id) header=1 for ps in cis.iread(CIO_PSF, conv_id=cv.conv_id, server=sv.server, server_class=sv.server_class, service=sv.service): # Persistent store selectors: puid or uid/token or uid or token or conv_id # class/server/service or any combination if header: ps.lprint(header=1,selectfields=PSF_FIELDS) header=0 ps.lprint(selectfields=PSF_FIELDS) print() # new line else: # no detail us = cis.iget(CIO_UOW_STATISTICS, server=sv.server, server_class=sv.server_class, service=sv.service) print() if us: # UOW Statistics us.dprint() else: print('No UOW statistics available for %s/%s/%s\n' %( sv.server_class,sv.server,sv.service)) if uid: print(80*'=') print('Broker clients with USER ID starting with %r' % uid) for ob in cis.iread(CIO_CLIENT): # Client selectors: uowid or uid/token or uid or token # server=sv.server,server_class=sv.server_class,service=sv.service) if not ob.uid.startswith(uid): # post selection continue ob.dprint(selectfields=CS_FIELDS) uidtok=(ob.uid,ob.token) svs = svcs_client[uidtok] if svs: print(' Client has total of %d CONVs and %d committed UOWs receivable with services' % ( conv_client.get(uidtok,0), uows_client.get(uidtok,0))) for sv in svs: print('\t',sv) print() #for i, ob in enumerate( # cis.iread(CIO_SERVER, uid='REPTOR-DA3F-----MM10007') ): # print('Server %d'%(i+1) # ob.dprint() __version__ = 'v.r.l' if __version__ == 'v.r.l': _svndate='$Date: 2023-12-01 00:54:33 +0100 (Fri, 01 Dec 2023) $' _svnrev='$Rev: 1072 $' __version__ = 'Dev ' + _svnrev.strip('$') + \ ' '.join(_svndate.strip('$').split()[0:3]) # Copyright 2004-ThisYear Software AG # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.