3131# simultaneously.
3232#------------------------------------------------------------------------------
3333
34- from . import errors
34+ import threading
3535
36- # this flag is used to indicate which mode is currently being used:
37- # None: neither thick nor thin implementation has been used yet
38- # False: thick implementation is being used
39- # True: thin implementation is being used
40- thin_mode = None
36+ from . import errors
4137
42- def check_and_return_mode (requested_thin_mode = None ):
38+ # The DriverModeHandler class is used to manage which mode the driver is using.
39+ #
40+ # The "thin_mode" flag contains the current state:
41+ # None: neither thick nor thin implementation has been used yet
42+ # False: thick implementation is being used
43+ # True: thin implementation is being used
44+ #
45+ # The "requested_thin_mode" flag is set to the mode that is being requested:
46+ # False: thick implementation is being initialized
47+ # True: thin implementation is being initialized
48+ class DriverModeManager :
4349 """
44- Internal function to return the current mode of python-oracledb.
50+ Manages the mode the driver is using. The "thin_mode" flag contains the
51+ current state:
52+ None: neither thick nor thin implementation has been used yet
53+ False: thick implementation is being used
54+ True: thin implementation is being used
55+ The "requested_thin_mode" is set to the mode that is being requested, but
56+ only while initialization is taking place (otherwise, it contains the value
57+ None):
58+ False: thick implementation is being initialized
59+ True: thin implementation is being initialized
60+ The condition is used to ensure that only one thread is performing
61+ initialization.
62+ """
63+ def __init__ (self ):
64+ self .thin_mode = None
65+ self .requested_thin_mode = None
66+ self .condition = threading .Condition ()
67+
68+ def __enter__ (self ):
69+ return self
4570
46- If neither the thick nor the thin implementation have been used yet (the
47- value of thin_mode is None), then:
71+ def __exit__ (self , exc_type , exc_value , exc_tb ):
72+ with self .condition :
73+ if exc_type is None and exc_value is None and exc_tb is None \
74+ and self .requested_thin_mode is not None :
75+ self .thin_mode = self .requested_thin_mode
76+ self .requested_thin_mode = None
77+ self .condition .notify ()
4878
49- - the mode is set to the requested mode, or
79+ @property
80+ def thin (self ):
81+ if self .requested_thin_mode is not None :
82+ return self .requested_thin_mode
83+ return self .thin_mode
5084
51- - the mode is set to thin, if no mode is requested.
85+ manager = DriverModeManager ()
5286
53- Otherwise, if requested_thin_mode is used and the mode requested
54- does not match the current mode, an error is raised.
87+ def get_manager (requested_thin_mode = None ):
88+ """
89+ Returns the manager, but only after ensuring that no other threads are
90+ attempting to initialize the mode.
5591
5692 NOTE: the current implementation of the driver only requires
5793 requested_thin_mode to be set when initializing the thick mode; for this
5894 reason the error raised is specified about a thin mode connection already
5995 being created. If this assumption changes, a new error message will be
6096 required.
6197 """
62- global thin_mode
63- if thin_mode is None :
64- if requested_thin_mode is None :
65- thin_mode = True
66- else :
67- thin_mode = requested_thin_mode
68- elif requested_thin_mode is not None and requested_thin_mode != thin_mode :
69- errors ._raise_err (errors .ERR_THIN_CONNECTION_ALREADY_CREATED )
70- return thin_mode
98+ with manager .condition :
99+ if manager .thin_mode is None :
100+ if manager .requested_thin_mode is not None :
101+ manager .condition .wait ()
102+ if manager .thin_mode is None :
103+ if requested_thin_mode is None :
104+ manager .requested_thin_mode = True
105+ else :
106+ manager .requested_thin_mode = requested_thin_mode
107+ elif requested_thin_mode is not None \
108+ and requested_thin_mode != manager .thin_mode :
109+ errors ._raise_err (errors .ERR_THIN_CONNECTION_ALREADY_CREATED )
110+ return manager
71111
72112
73113def is_thin_mode () -> bool :
@@ -77,14 +117,14 @@ def is_thin_mode() -> bool:
77117
78118 Immediately after python-oracledb is imported, this function will return
79119 True indicating that python-oracledb defaults to Thin mode. If
80- oracledb.init_oracle_client() is called, then a subsequent call to
81- is_thin_mode() will return False indicating that Thick mode is enabled.
82- Once the first standalone connection or connection pool is created, or a
83- call to oracledb.init_oracle_client() is made, then python-oracledb's mode
84- is fixed and the value returned by is_thin_mode() will never change for the
85- lifetime of the process.
120+ oracledb.init_oracle_client() is called successfully , then a subsequent
121+ call to is_thin_mode() will return False indicating that Thick mode is
122+ enabled. Once the first standalone connection or connection pool is
123+ created succesfully, or a call to oracledb.init_oracle_client() is made
124+ successfully, then python-oracledb's mode is fixed and the value returned
125+ by is_thin_mode() will never change for the lifetime of the process.
86126
87127 """
88- if thin_mode is not None :
89- return thin_mode
128+ if manager . thin_mode is not None :
129+ return manager . thin_mode
90130 return True
0 commit comments