def _EndProcess_(self, vDbFullName, secure, mcc, ta): self._m_pool_ = CSocketPool(self._m_clsAsyncHandler_, not self._m_rs_.NoAutoConn, self._m_rs_.RecvTimeout, self._m_rs_.ConnTimeout) if secure: def AuthInternal(sender, cs): if cs.ConnectionContext.Port == 0xffff or cs.ConnectionContext.Port == -1: return True return self.DoSslServerAuthentication(cs) self._m_pool_.DoSslServerAuthentication = AuthInternal def PoolEvent(sender, spe, handler): if spe == tagSocketPoolEvent.speSocketClosed: handler.CleanCallbacks() elif spe == tagSocketPoolEvent.speConnecting: if handler.AttachedClientSocket.ConnectionContext.Port == 0xffff or handler.AttachedClientSocket.ConnectionContext.Port == -1: handler.AttachedClientSocket.ConnectingTimeout = 500 else: pass self._m_pool_.SocketPoolEvent = PoolEvent ok = self._m_pool_.StartSocketPoolEx(mcc, True, ta) n = 0 for s in self._m_pool_.Sockets: key = vDbFullName[n] ok = s.ClientQueue.StartQueue(key, self._m_rs_.TTL, secure) n += 1 if self.Replicable: self.SourceQueue.EnsureAppending(self.TargetQueues) targetHandlers = self.TargetHandlers for h in targetHandlers: ok = h.AttachedClientSocket.DoEcho()
from loading_balance.lb_worker.piworker import PiWorker from spa.clientside import CConnectionContext, CSocketPool import sys, multiprocessing print('Worker: tell me load balance host address:') cc = CConnectionContext(sys.stdin.readline().strip(), 20901, "lb_worker", "pwdForlbworker") with CSocketPool(PiWorker) as spPi: if not spPi.StartSocketPool(cc, 1, multiprocessing.cpu_count()): print('No connection to ' + cc.Host) print('Press ENTER key to kill the demo ......') line = sys.stdin.readline()
class CReplication(object): _DIR_SEP_ = '/' if CUQueue.DEFAULT_OS == tagOperationSystem.osWin: _DIR_SEP_ = '\\' def __del__(self): self._Cleanup() def __enter__(self): return self def __exit__(self, type, value, traceback): self._Cleanup() def _Cleanup(self): if not self._m_pool_ is None: self._m_pool_.ShutdownPool() self._m_pool_ = None #<summary> #Construct a CReplication instance #</summary> #<param name="clsAsyncHandler">An async handler derived from CAsyncServiceHandler</param> #<param name="qms">A structure for setting its underlying socket pool and message queue directory as well as password for source queue</param> def __init__(self, clsAsyncHandler, qms): self._m_clsAsyncHandler_ = clsAsyncHandler self._m_mapQueueConn_ = {} self._m_pool_ = None self._CheckReplicationSetting_(qms) def DoSslServerAuthentication(self, cs): return True @property def Connections(self): if self._m_pool_ is None: return 0 return self._m_pool_.ConnectedSockets @property def Replicable(self): return len(self._m_mapQueueConn_) > 1 @property def SourceHandler(self): if self._m_pool_ is None: return None one = None for h in self._m_pool_.AsyncHandlers: one = h return one @property def SourceQueue(self): src = self.SourceHandler if src is None: return None return src.AttachedClientSocket.ClientQueue @property def TargetQueues(self): handlers = self.TargetHandlers if handlers is None: return None tq = [] for h in handlers: tq.append(h.AttachedClientSocket.ClientQueue) return tq @property def TargetHandlers(self): if self._m_pool_ is None: return None tq = [] for h in self._m_pool_.AsyncHandlers: tq.append(h) if len(tq) >= len(self._m_mapQueueConn_): break return tq @property def Hosts(self): return len(self._m_mapQueueConn_) @property def Queues(self): if self._m_pool_ is None: return 0 return self._m_pool_.Queues @property def ReplicationSetting(self): return self._m_rs_ """ <summary> Make a replication. An invalid operation exception will be thrown if not replicable. </summary> <returns>True for success; and false for failure</returns> """ def DoReplication(self): if len(self._m_mapQueueConn_) == 1: raise Exception( 'No replication is allowed because the number of target message queues less than two' ) src = self.SourceQueue if src is None: return False return src.AppendTo(self.TargetQueues) def _DoesQueueExist_(self, qName): ignoreCase = False if CUQueue.DEFAULT_OS == tagOperationSystem.osWin: ignoreCase = True for name in self._m_mapQueueConn_.keys(): if ignoreCase: if name.lower() == qName.lower(): return True else: if name == qName: return True return False def Send(self, reqId, q): src = self.SourceHandler if src is None: return False cq = src.AttachedClientSocket.ClientQueue if not cq.Available: return False ok = src.SendRequest(reqId, q, None) if self.Replicable and cq.JobSize == 0: ok = cq.AppendTo(self.TargetQueues) return ok def EndJob(self): src = self.SourceQueue if src is None or not src.Available: return False ok = src.EndJob() if ok and self.Replicable: ok = src.AppendTo(self.TargetQueues) return ok def StartJob(self): src = self.SourceQueue if src is None or not src.Available: return False return src.StartJob() def AbortJob(self): src = self.SourceQueue if src is None or not src.Available: return False return src.AbortJob() def _EndProcess_(self, vDbFullName, secure, mcc, ta): self._m_pool_ = CSocketPool(self._m_clsAsyncHandler_, not self._m_rs_.NoAutoConn, self._m_rs_.RecvTimeout, self._m_rs_.ConnTimeout) if secure: def AuthInternal(sender, cs): if cs.ConnectionContext.Port == 0xffff or cs.ConnectionContext.Port == -1: return True return self.DoSslServerAuthentication(cs) self._m_pool_.DoSslServerAuthentication = AuthInternal def PoolEvent(sender, spe, handler): if spe == tagSocketPoolEvent.speSocketClosed: handler.CleanCallbacks() elif spe == tagSocketPoolEvent.speConnecting: if handler.AttachedClientSocket.ConnectionContext.Port == 0xffff or handler.AttachedClientSocket.ConnectionContext.Port == -1: handler.AttachedClientSocket.ConnectingTimeout = 500 else: pass self._m_pool_.SocketPoolEvent = PoolEvent ok = self._m_pool_.StartSocketPoolEx(mcc, True, ta) n = 0 for s in self._m_pool_.Sockets: key = vDbFullName[n] ok = s.ClientQueue.StartQueue(key, self._m_rs_.TTL, secure) n += 1 if self.Replicable: self.SourceQueue.EnsureAppending(self.TargetQueues) targetHandlers = self.TargetHandlers for h in targetHandlers: ok = h.AttachedClientSocket.DoEcho() def _CheckReplicationSetting_(self, qms): if qms.TTL == 0: qms.TTL = ReplicationSetting.DEAFULT_TTL if qms.ConnTimeout == 0: qms.ConnTimeout = CClientSocket.DEFAULT_CONN_TIMEOUT if qms.RecvTimeout == 0: qms.RecvTimeout = CClientSocket.DEFAULT_RECV_TIMEOUT if qms.QueueDir is None: raise ValueError('An absolute path required for working directory') qms.QueueDir = qms.QueueDir.strip() if len(qms.QueueDir) == 0: raise ValueError('An absolute path required for working directory') if not os.path.exists(qms.QueueDir): os.makedirs(qms.QueueDir) self._m_rs_ = qms.Copy() def _CheckConnQueueName_(self, mapQueueConn): self._m_mapQueueConn_.clear() if mapQueueConn is None or len(mapQueueConn) == 0: raise ValueError('One middle server required at least') for key, cc in mapQueueConn.items(): if cc is None: raise ValueError('An invalid host found') if key is None or len(key) == 0: raise ValueError( 'A non-empty string for persistent queue name required for each of hosts' ) if self._DoesQueueExist_(key): raise Exception('Queue name duplicated -- ' + key) self._m_mapQueueConn_[key] = cc #<summary> #Start a socket pool for replication #</summary> #<param name="mapQueueConn">A dictionary for message queue name and connecting context. a unique name must be specified for each of connecting contexts</param> #<param name="rootQueueName">A string for root replication queue name. It is ignored if it is not replicable</param> #<param name="ta">COM thread apartment; and it defaults to taNone. It is ignored on non-window platforms</param> #<returns>True if there is at least one connection established; and false if there is no connection</returns> def Start(self, mapQueueConn, rootQueueName='', ta=0): self._CheckConnQueueName_(mapQueueConn) n = 0 secure = False all = len(self._m_mapQueueConn_) if all > 1: all += 1 if rootQueueName is None: rootQueueName = '' rootQueueName = rootQueueName.strip() if len(rootQueueName) == 0: appName = os.path.basename(__file__) dot = appName.rindex('.') if dot == -1: rootQueueName = appName else: rootQueueName = appName[0:dot] vDbFullName = [] mcc = [[]] for key in self._m_mapQueueConn_.keys(): mcc[0].append(self._m_mapQueueConn_[key]) if not secure and mcc[0][ n].EncrytionMethod == tagEncryptionMethod.TLSv1: secure = True vDbFullName.append(self._m_rs_.QueueDir + key) n += 1 if all > 1: last = CConnectionContext('127.0.0.1', 0xffff, 'UReplication', '', tagEncryptionMethod.NoEncryption) if secure: last.EncrytionMethod = tagEncryptionMethod.TLSv1 mcc[0].append(last) vDbFullName.append(self._m_rs_.QueueDir + rootQueueName) self._EndProcess_(vDbFullName, secure, mcc, ta) return self._m_pool_.ConnectedSockets > 0
import sys from spa.udb import * from spa import CServerError as Se from spa import Pair from spa.clientside import CSocketPool, CConnectionContext, CMysql, CUQueue, CSocketError import datetime # prepare two large texts g_wstr = u'' while len(g_wstr) < 128 * 1024: g_wstr += u'近日,一则极具震撼性的消息,在中航工业的干部职工中悄然流传:中航工业科技委副主任、总装备部先进制造技术专家组组长、原中航工业制造所所长郭恩明突然失联。老郭突然失联,在中航工业和国防科技工业投下了震撼弹,也给人们留下了难以解开的谜团,以正面形象示人的郭恩明,为什么会涉足谍海,走上不归路,是被人下药被动失足?还是没能逃过漂亮“女间谍“的致命诱惑?还是仇视社会主义,仇视航空工业,自甘堕落与国家与人民为敌?' g_astr = '' while len(g_astr) < 256 * 1024: g_astr += 'The epic takedown of his opponent on an all-important voting day was extraordinary even by the standards of the 2016 campaign -- and quickly drew a scathing response from Trump.' with CSocketPool(CMysql) as spMysql: print('Remote async mysql server host: ') cc = CConnectionContext(sys.stdin.readline(), 20902, 'root', 'Smash123') ok = spMysql.StartSocketPool(cc, 1) mysql = spMysql.AsyncHandlers[0] if not ok: print('No connection error code = ' + str(mysql.Socket.ErrorCode)) exit(0) def TestCreateTables(): return [ mysql.execute( 'CREATE DATABASE IF NOT EXISTS mysqldb character set utf8 collate utf8_general_ci;USE mysqldb' ), mysql.execute( 'CREATE TABLE IF NOT EXISTS company(ID bigint PRIMARY KEY NOT NULL,name CHAR(64)'
from hello_world.client.asynchelloworld import CHelloWorld from spa import CScopeUQueue as Sb, CServerError from spa.clientside import CSocketPool, CConnectionContext, CSocketError from consts import hwConst from msstruct import CMyStruct import sys with CSocketPool(CHelloWorld) as sp: cc = CConnectionContext('localhost', 20901, 'PythonUser', 'TooMuchSecret') # sp.QueueName = 'pqueue' # turn on client message queue for backing up requests if not sp.StartSocketPool(cc, 1): print('Cannot connect to server with error message: ' + sp.Sockets[0].ErrMsg) else: hw = sp.Seek() ms = CMyStruct.MakeOne() # make a complex structure print(ms) # process requests one by one synchronously -- three round trips try: print(hw.say_hello(u'Jack', u'Smith')) hw.sleep(4000) print(hw.echo(ms)) except CServerError as ex: # an exception from remote server print(ex) except CSocketError as ex: # a communication error print(ex) except Exception as ex: # invalid parameter, bad de-serialization, and so on print('Unexpected error: ' + str(ex)) print('')
return True return False #not processed aq.ResultReturned = cbResultReturned def cbDequeue(aq, messageCount, fileSize, messages, bytes): s = 'Total message count=' + str(messageCount) + ', queue file size=' + str(fileSize) + ', messages dequeued=' + str(messages) + ', message bytes dequeued=' + str(bytes) print(s) if messageCount > 0: # there are more messages left at server queue, we re-send a request to dequeue aq.Dequeue(TEST_QUEUE_KEY, aq.LastDequeueCallback) print('Going to dequeue messages ......') aq.Dequeue(TEST_QUEUE_KEY, cbDequeue) #optionally, add one extra to improve processing concurrency at both client and server sides for better performance and through-output aq.Dequeue(TEST_QUEUE_KEY, cbDequeue) with CSocketPool(CAsyncQueue) as spAq: print('Remote async queue server host: ') cc = CConnectionContext(sys.stdin.readline(), 20901, 'PythonUser', 'TooMuchSecret') ok = spAq.StartSocketPool(cc, 1, 1) aq = spAq.AsyncHandlers[0] if not ok: print('No connection error code = ' + str(aq.AttachedClientSocket.ErrorCode)) exit(0) #Optionally, you can enqueue messages with transaction style by calling the methods StartQueueTrans and EndQueueTrans in pair #aq.StartQueueTrans(TEST_QUEUE_KEY, lambda errCode: print('errCode=' + str(errCode))) TestEnqueue(aq) #aq.EndQueueTrans() TestDequeue(aq) print('Press any key to close the application ......')
if not sqlite.EndTrans(tagRollbackPlan.rpDefault, cbx, canceled): break sp.Unlock(sqlite) # put handler back into pool for reuse ok = True break # break while loop if not ok: with m_csConsole: print('DoFuture: Connection disconnected error code = ' + str(sqlite.AttachedClientSocket.ErrorCode) + ', message = ' + sqlite.AttachedClientSocket.ErrorMessage) f.set(False) return f with CSocketPool(CSqlite) as spSqlite: print('Remote async sqlite server host: ') cc = CConnectionContext(sys.stdin.readline(), 20901, 'PythonUser', 'TooMuchSecret') # start socket pool having 1 worker which hosts 2 non-block sockets ok = spSqlite.StartSocketPool(cc, 2, 1) if not ok: print( 'No connection to sqlite server and press any key to close the demo ......' ) sys.stdin.readline() exit(0) sqlite = spSqlite.AsyncHandlers[0] # Use the above bad implementation to replace original spa.clientside.CAsyncDBHandler.Open method # at file socketpro/bin/spa/clientside/asyncdbhandler.py for cross SendRequest dead lock demonstration print('Doing Demo_Cross_Request_Dead_Lock ......')
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys from spa.udb import * from spa import Pair from spa.clientside import CSocketPool, CConnectionContext, COdbc, CUQueue from spa.udb import CParameterInfo import datetime from decimal import Decimal with CSocketPool(COdbc) as spOdbc: print('Remote async odbc server host: ') cc = CConnectionContext(sys.stdin.readline(), 20901, 'odbcUser', 'TooMuchSecret') ok = spOdbc.StartSocketPool(cc, 1, 1) odbc = spOdbc.AsyncHandlers[0] if not ok: print('No connection error code = ' + str(odbc.AttachedClientSocket.ErrorCode)) spOdbc.ShutdownPool() exit(0) def cb(odbc, res, errMsg): print('res = ' + str(res) + ', errMsg: ' + errMsg) def cbExecute(odbc, res, errMsg, affected, fail_ok, lastRowId): print('affected = ' + str(affected) + ', fails = ' + str(fail_ok >> 32) + ', oks = ' + str(fail_ok & 0xffffffff) + ', res = ' + str(res) + ', errMsg: ' + errMsg) def TestCreateTables(): ok = odbc.ExecuteSql('CREATE DATABASE IF NOT EXISTS mysqldb character set utf8 collate utf8_general_ci;USE mysqldb', cbExecute) ok = odbc.ExecuteSql('CREATE TABLE IF NOT EXISTS company(ID bigint PRIMARY KEY NOT NULL,name CHAR(64)NOT NULL,ADDRESS varCHAR(256)not null,Income decimal(15,2)not null)', cbExecute) ok = odbc.ExecuteSql('CREATE TABLE IF NOT EXISTS employee(EMPLOYEEID bigint AUTO_INCREMENT PRIMARY KEY NOT NULL unique,CompanyId bigint not null,name CHAR(64)NOT NULL,JoinDate DATETIME default null,IMAGE MEDIUMBLOB,DESCRIPTION MEDIUMTEXT,Salary decimal(15,2),FOREIGN KEY(CompanyId)REFERENCES company(id))', cbExecute)