· 9 years ago · Jan 01, 2017, 11:38 PM
1# Import the super class for this class.
2# ModThread is just a threading.Thread class
3# with some additional variables that necessary
4# specifically for this program.
5from mod_thread import ModThread as mt
6
7# Import Python json library for JSON manipulation.
8import json
9
10# Import RethinkDB Python library to manipulate
11# RethinkDB database.
12import rethinkdb as r
13
14class InsertDatabase(mt):
15
16 # The constructor. The _conn is the current connection
17 # to _db. So, the _db class is the database information,
18 # while the _conn is the variable that hold connection
19 # between this program and the database.
20 def __init__(self, _threadName, _array,
21 _db, _conn, _config):
22
23 #print(type(_array))
24
25 # Append this array into database.
26 _array.append(self)
27
28 # Initiate the super class.
29 mt.__init__(self,
30 _array.index(self) + 1,
31 _array.index(self) + 1, _threadName)
32
33 # Class wide variables that hold reference to
34 # the connected database.
35 self.db = _db
36 self.conn = _conn
37 # Shared variables.
38 self.config = _config
39 # Specifically for table, it will be checked and
40 # generated from this class if the destined table
41 # is not exists yet.
42 self.table = None
43
44 # The main array that holds all data that will
45 # be inserted into specific table in self.db.
46 self.mainArray = []
47
48 def run(self):
49
50 while self.killMe == False:
51
52 # Check if there is at least one element in the
53 # main array. The mainArray is the array that
54 # list all element that will be put into database
55 # before it pops.
56 if len(self.mainArray) > 0:
57
58 # Initiate empty JSON array.
59 jsonRaw = {}
60 # The cooked JSON array ready to be
61 # served into database :d :d :d.
62 jsonCooked = {}
63
64 # Take the FIRST element in the main array.
65 # The first element in the main array is the
66 # earliest element that was added into the
67 # main array.
68 firstElement = self.mainArray[0]
69
70 # The first element of the firstElement is
71 # from which sensor the data is coming from.
72 # In this example there are two sensors which
73 # are the cam and microphone.
74 sensorSource = firstElement[0]
75 # The table name of which data should be stored.
76 tableName = self.config.cfgClientName + "_" + sensorSource
77
78 # The next elements after the first elements
79 # are for time stamps. I am making it with
80 # timezone in case there is a necessity to
81 # test the project with remote office environment.
82 # Put the available data.
83 jsonRaw["year"] = firstElement[1] # Year.
84 jsonRaw["month"] = firstElement[2] # Month.
85 jsonRaw["day"] = firstElement[3] # Day.
86 jsonRaw["hour"] = firstElement[4] # Hour.
87 jsonRaw["minutes"] = firstElement[5] # Minute.
88 jsonRaw["second"] = firstElement[6] # Second.
89
90 #print(jsonRaw["second"])
91
92 jsonRaw["utc"] = firstElement[7] # Timezone.
93
94 # Next elements are the sensor data itself. So,
95 # here I try to parse the data from the index
96 # after 8 in firstElement. The first even index
97 # after is the field name of the value (for
98 # example, pitch or volume). While the odd index
99 # after index 7 is the value of its previous index.
100 #
101 # For example:
102 #
103 # Index 8 is pitch. Then index 9 is the value of
104 # the pitch.
105 # Index 9 is force. Then index 10 is the value of
106 # the force.
107 index = 8
108 while index < len(firstElement):
109
110 # Parse the field name.
111 fieldName = firstElement[index]
112 index = index + 1
113 # Parse the value.
114 value = firstElement[index]
115 index = index + 1
116 jsonRaw[fieldName] = value
117
118 # Cooked the JSON so that it is ready to be served
119 # to the database.
120 jsonCooked = json.dumps(jsonRaw)
121 # jsonCooked is still a string, hence I need to
122 # format it again so that it become dictionary.
123 jsonCookedAgain = json.loads(jsonCooked)
124
125 # Check if the target table is exist in the
126 # database. If the target table is not exist
127 # then create a new table.
128 #
129 # On, 23rd December 2016 there is a problem
130 # that the read request to the database is
131 # getting exponentially higher over times.
132 # After commenting right there and here the
133 # culprit is this try catch statement below.
134 #
135 # The problem here is that I need to check
136 # if a table exist or not by using these codes
137 # self.db.table(tableName).run(self.conn).
138 # However, those codes makes the exponentially
139 # increase read request over time. In the other
140 # hand I need to know if the table is exists or
141 # not without using the connection codes.
142 #
143 # The solution is to do try checking when a
144 # document inserted. And not to do try checking
145 # if a table is exists.
146 try:
147
148 #self.db.table(tableName).run(self.conn)
149 self.table = self.db.table(tableName)
150 # Insert the jsonCookedAgain into the database.
151 # The fix to exponentially higher is to do try
152 # statement for the insert database instead of
153 # checking the connection.
154 dataInserted = self.table.insert(jsonCookedAgain).run(self.conn)
155
156 #print(dataInserted)
157 #print(self.table)
158
159 except r.ReqlOpFailedError as error:
160
161 print(
162 "Table for " +
163 self.config.cfgClientName +
164 " to store " +
165 sensorSource +
166 " data does not exist."
167 )
168 print("Creating " + tableName + " table.")
169 self.db.table_create(tableName).run(self.conn)
170 self.table = self.db.table(tableName)
171
172 print(jsonCooked)
173
174 # Pop the first element of the array!
175 self.mainArray.pop(0)
176
177# Function to initiating connection to database.
178def ConnDB(_config, _conn, _db):
179
180 # Try to connecting to RethinkDB server.
181 # If without_database flag is False and
182 # the connection from this application to
183 # the database failed then halt this
184 # program.
185 try:
186
187 # The default port to connect is the
188 # localhost "127.0.0.1" (in string).
189 # Whereas the default port for RethinkDB
190 # is 28015.
191 #
192 # In local you can run RethinkDB with
193 # using `rethinkdb` command from terminal.
194 # From hosted environment (like
195 # DigitalOcean) run RethinkDB using
196 # `rethinkdb --bind all` from SSH - ed
197 # terminal.
198 #
199 # Connect into database.
200 _conn = r.connect(
201 host=_config.dbAddress[2],
202 port=_config.dbPort[2])
203
204 # Pick which database to get its
205 # information stored.
206 _db = r.db(config.dbName[2])
207
208 # If connection success return True.
209 return True
210
211 except r.errors.ReqlDriverError as error:
212
213 # Print the error.
214 print("connection to database error with error code of " + error)
215 print("please check database")
216 print("or check database configuration from this application")
217 print("re - trying connection")
218
219 # Run this function again until the connection
220 # to database established or the user stopped
221 # this application.
222 self.ConnDB(_config, _conn, _db)