Changeset: fd01b17e9fea for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=fd01b17e9fea
Modified Files:
clients/iotclient/src/Flask/app.py
clients/iotclient/src/Settings/filesystem.py
clients/iotclient/src/Settings/mapiconnection.py
clients/iotclient/src/Streams/streams.py
clients/iotclient/src/main.py
Branch: iot
Log Message:
Added option to add hostname as a stream column.
diffs (truncated from 306 to 300 lines):
diff --git a/clients/iotclient/src/Flask/app.py
b/clients/iotclient/src/Flask/app.py
--- a/clients/iotclient/src/Flask/app.py
+++ b/clients/iotclient/src/Flask/app.py
@@ -1,7 +1,7 @@
from flask import Flask
from flask_restful import Api
-from restresources import StreamInput, StreamsInfo, StreamsHandling # ,
ServerHandler
+from restresources import StreamInput, StreamsInfo, StreamsHandling
def start_flask_iot_app(host, port):
@@ -21,5 +21,4 @@ def start_flask_admin_app(host, port):
admin_api.add_resource(StreamsInfo, '/streams')
admin_api.add_resource(StreamsHandling, '/context')
- # admin_api.add_resource(ServerHandler, '/server')
admin_app.run(host=host, port=port, threaded=True)
diff --git a/clients/iotclient/src/Settings/filesystem.py
b/clients/iotclient/src/Settings/filesystem.py
--- a/clients/iotclient/src/Settings/filesystem.py
+++ b/clients/iotclient/src/Settings/filesystem.py
@@ -5,22 +5,24 @@ from Utilities.filecreator import create
BASKETS_BASE_DIRECTORY = "baskets"
CONFIG_FILE_DEFAULT_NAME = "config.json"
-Baskets_Base_Location = None
-Config_File_Location = None
if sys.platform in ("linux", "linux2", "darwin"):
filesystem_location = '/etc/iotcollector'
elif sys.platform == "win32":
filesystem_location = os.path.dirname(os.path.realpath(__file__))
+Baskets_Base_Location = None
+Config_File_Location = None
+Host_Identifier = None
+
def set_filesystem_location(new_location):
global filesystem_location
filesystem_location = new_location
-def init_file_system(new_configfile_location=None):
- global Baskets_Base_Location, Config_File_Location
+def init_file_system(host_identifier=None, new_configfile_location=None):
+ global Baskets_Base_Location, Config_File_Location, Host_Identifier
try:
Baskets_Base_Location = os.path.join(filesystem_location,
BASKETS_BASE_DIRECTORY)
@@ -32,6 +34,8 @@ def init_file_system(new_configfile_loca
else:
Config_File_Location = create_file_if_not_exists(
os.path.join(filesystem_location, CONFIG_FILE_DEFAULT_NAME),
hidden=False, init_text='[]')
+
+ Host_Identifier = host_identifier
except (Exception, OSError) as ex:
print >> sys.stderr, ex
sys.exit(1)
@@ -43,3 +47,7 @@ def get_baskets_base_location():
def get_configfile_location():
return Config_File_Location
+
+
+def get_host_identifier():
+ return Host_Identifier
diff --git a/clients/iotclient/src/Settings/mapiconnection.py
b/clients/iotclient/src/Settings/mapiconnection.py
--- a/clients/iotclient/src/Settings/mapiconnection.py
+++ b/clients/iotclient/src/Settings/mapiconnection.py
@@ -28,11 +28,15 @@ def mapi_create_stream(schema, stream, c
Connection.execute("CREATE SCHEMA " + schema + ";")
except:
pass
- sql_str = ''.join(["CREATE STREAM TABLE ", schema, ".", stream, " (",
columns, ");"])
- Connection.execute(sql_str)
+
+ try: # attempt to create te stream table
+ Connection.execute(''.join(["CREATE STREAM TABLE ", schema, ".",
stream, " (", columns, ");"]))
+ except:
+ pass
def mapi_flush_baskets(schema, stream, baskets):
- # this procedure does not work yet. Have to check it with Martin
- # Connection.execute(''.join(["CALL iot.push(\"", schema, "\",\"", stream,
"\",\"", baskets, "\");"]))
- pass
+ try:
+ Connection.execute(''.join(["CALL iot.push(\"", schema, "\",\"",
stream, "\",\"", baskets, "\");"]))
+ except:
+ pass
diff --git a/clients/iotclient/src/Streams/streams.py
b/clients/iotclient/src/Streams/streams.py
--- a/clients/iotclient/src/Streams/streams.py
+++ b/clients/iotclient/src/Streams/streams.py
@@ -1,16 +1,14 @@
import os
from collections import defaultdict
-from datatypes import TimestampType, DataValidationException
+from datatypes import TimestampType, TextType, DataValidationException
from flushing import TimeBasedFlushing, TupleBasedFlushing
from Settings.mapiconnection import mapi_create_stream, mapi_flush_baskets
-from Settings.filesystem import get_baskets_base_location
+from Settings.filesystem import get_baskets_base_location, get_host_identifier
from Settings.iotlogger import add_log
from Utilities.filecreator import create_file_if_not_exists,
get_hidden_file_name
from Utilities.readwritelock import RWLock
-IMPLICIT_TIMESTAMP_COLUMN_NAME = 'implicit_timestamp'
-
def represents_int(s):
try:
@@ -19,6 +17,23 @@ def represents_int(s):
except ValueError:
return False
+IMPLICIT_TIMESTAMP_COLUMN_NAME = 'implicit_timestamp'
+Timestamps_Handler = TimestampType(name=IMPLICIT_TIMESTAMP_COLUMN_NAME,
type="timestamp") # timestamp
+Create_SQL_array = [Timestamps_Handler.create_stream_sql()] # array for SQL
creation
+
+HOST_IDENTIFIER_COLUMN_NAME = 'host_identifier'
+Hostname_Bin_Value = None
+
+
+def init_streams_hosts():
+ global Hostname_Bin_Value
+
+ host_identifier = get_host_identifier()
+ if host_identifier is not None:
+ hosts_handler = TextType(name=HOST_IDENTIFIER_COLUMN_NAME,
type="text") # host_identifier
+ Hostname_Bin_Value = hosts_handler.process_values([host_identifier])
+ Create_SQL_array.append(hosts_handler.create_stream_sql())
+
class StreamException(Exception):
"""Exception fired when the validation of a stream insert fails"""
@@ -36,10 +51,10 @@ class DataCellStream(object):
self._tuples_in_per_basket = 0 # for efficiency
self._flush_method = flush_method # instance of StreamFlushingMethod
self._columns = columns # dictionary of name -> data_types
- self._timestamps_handler =
TimestampType(name=IMPLICIT_TIMESTAMP_COLUMN_NAME, type="timestamp") #
timestamp
self._validation_schema = validation_schema # json validation schema
for the inserts
self._monitor = RWLock() # baskets lock to protect files (the server
is multi-threaded)
self._base_path = os.path.join(get_baskets_base_location(),
schema_name, stream_name)
+
if not os.path.exists(self._base_path):
os.makedirs(self._base_path)
self._baskets_counter = 1
@@ -49,18 +64,21 @@ class DataCellStream(object):
for elem in dirs: # for each directory found, flush it
dir_path = os.path.join(self._base_path, str(elem))
mapi_flush_baskets(self._schema_name, self._stream_name,
dir_path)
- self._baskets_counter = max(dirs) + 1 # the current basket
number will be the next one
+ self._baskets_counter = max(dirs) + 1 # increment current
basket number
else:
self._baskets_counter = 1
self._current_base_path = os.path.join(self._base_path,
str(self._baskets_counter))
os.makedirs(self._current_base_path)
+
for key in self._columns.keys(): # create the files for the columns
and timestamp
create_file_if_not_exists(os.path.join(self._current_base_path,
key), hidden=True)
create_file_if_not_exists(os.path.join(self._current_base_path,
IMPLICIT_TIMESTAMP_COLUMN_NAME), hidden=True)
+ if Hostname_Bin_Value is not None:
+ create_file_if_not_exists(os.path.join(self._current_base_path,
HOST_IDENTIFIER_COLUMN_NAME), hidden=True)
if created: # when the stream is reloaded from the config file, the
create SQL statement is not sent
- column_string = ','.join([column.create_stream_sql() for column in
self._columns.values()])
- mapi_create_stream(self._schema_name, self._stream_name,
column_string)
+ sql_array = [column.create_stream_sql() for column in
self._columns.values()]
+ mapi_create_stream(self._schema_name, self._stream_name,
','.join(sql_array + Create_SQL_array))
def get_schema_name(self):
return self._schema_name
@@ -101,10 +119,14 @@ class DataCellStream(object):
self._baskets_counter += 1
self._current_base_path = os.path.join(self._base_path,
str(self._baskets_counter))
os.makedirs(self._current_base_path)
+
for key in self._columns.keys():
create_file_if_not_exists(os.path.join(self._current_base_path, key),
hidden=True)
create_file_if_not_exists(os.path.join(self._current_base_path,
IMPLICIT_TIMESTAMP_COLUMN_NAME),
hidden=True)
+ if Hostname_Bin_Value is not None:
+
create_file_if_not_exists(os.path.join(self._current_base_path,
HOST_IDENTIFIER_COLUMN_NAME),
+ hidden=True)
def time_based_flush(self, last=False):
self._monitor.acquire_write()
@@ -152,13 +174,17 @@ class DataCellStream(object):
# prepare variables outside the lock for more parallelism
total_tuples = len(new_data)
- bin_value = self._timestamps_handler.process_values([timestamp])
- timestamps_binary_array = ''.join([bin_value for _ in
xrange(total_tuples)])
+
+ timestamp_bin_value = Timestamps_Handler.process_values([timestamp])
+ timestamps_binary_array = ''.join([timestamp_bin_value for _ in
xrange(total_tuples)])
+
+ if Hostname_Bin_Value is not None:
+ hosts_binary_array = ''.join([Hostname_Bin_Value for _ in
xrange(total_tuples)])
+
+ # supposing that the flushing method never changes we can do this
outside the lock
is_flushing_tuple_based = isinstance(self._flush_method,
TupleBasedFlushing)
- # supposing that the flushing method never changes we can do this
outside the lock
self._monitor.acquire_write()
-
for key, inserts in transposed_data.iteritems(): # now write the
binary data
# open basket in binary mode and append the new entries
basket_fp =
open(get_hidden_file_name(os.path.join(self._current_base_path, key)), 'ab')
@@ -173,6 +199,13 @@ class DataCellStream(object):
time_basket_fp.flush()
time_basket_fp.close()
+ if Hostname_Bin_Value is not None: # write the host name if applicable
+ hosts_basket_fp =
open(get_hidden_file_name(os.path.join(self._current_base_path,
+
HOST_IDENTIFIER_COLUMN_NAME)), 'ab')
+ hosts_basket_fp.write(hosts_binary_array)
+ hosts_basket_fp.flush()
+ hosts_basket_fp.close()
+
self._tuples_in_per_basket += total_tuples
if is_flushing_tuple_based and self._tuples_in_per_basket >=
self._flush_method.limit:
self.flush_baskets(last=False)
diff --git a/clients/iotclient/src/main.py b/clients/iotclient/src/main.py
--- a/clients/iotclient/src/main.py
+++ b/clients/iotclient/src/main.py
@@ -2,8 +2,9 @@ import getopt
import sys
import threading
+from uuid import getnode as get_mac
from Settings import filesystem, iotlogger
-from Streams import streamscontext
+from Streams import streamscontext, streams
from Flask import restresources
from Flask.app import start_flask_iot_app, start_flask_admin_app
from Settings.mapiconnection import init_monetdb_connection
@@ -11,9 +12,11 @@ from Settings.mapiconnection import init
def main(argv):
try:
- opts, args = getopt.getopt(argv[1:], 'f:l:c:ih:ip:ah:ap:ch:cp:cd:cu',
- ['filesystem=', 'logfile=', 'configfile=',
'ihost=', 'iport=', 'ahost=', 'aport=',
- 'chostname=', 'cport=', 'cdatabase=',
'cuser='])
+ opts, args = getopt.getopt(argv[1:],
'f:l:c:u:n:ih:ip:ah:ap:dh:dp:dd:du',
+ ['filesystem=', 'logfile=', 'configfile=',
'useidentifier=', 'name='
+
'ihost=', 'iport=',
+ 'ahost=', 'aport=',
+ 'dhostname=', 'dport=', 'ddatabase=',
'duser='])
except getopt.GetoptError:
print >> sys.stderr, "Error while parsing the arguments!"
sys.exit(1)
@@ -28,7 +31,10 @@ def main(argv):
connection_port = 50000
connection_user = 'monetdb'
connection_database = 'iotdb'
+
new_configfile_location = None
+ use_host_identifier = False
+ host_identifier = None
for opt, arg in opts:
if opt in ('-f', '--filesystem'):
@@ -37,6 +43,10 @@ def main(argv):
iotlogger.set_logging_location(arg)
elif opt in ('-c', '--configfile'):
new_configfile_location = arg
+ elif opt in ('-u', '--useidentifier'):
+ use_host_identifier = bool(arg)
+ elif opt in ('-n', '--name'):
+ host_identifier = arg
elif opt in ('-ih', '--ihost'):
app_host = arg
@@ -47,18 +57,24 @@ def main(argv):
elif opt in ('-ap', '--aport'):
admin_port = int(arg)
- elif opt in ('-ch', '--chostname'):
+ elif opt in ('-dh', '--dhostname'):
connection_hostname = arg
- elif opt in ('-cp', '--cport'):
+ elif opt in ('-dp', '--dport'):
connection_port = int(arg)
- elif opt in ('-cu', '--cuser'):
+ elif opt in ('-du', '--duser'):
connection_user = arg
- elif opt in ('-cd', '--cdatabase'):
+ elif opt in ('-dd', '--ddatabase'):
connection_database = arg
+ if use_host_identifier and host_identifier is None: # get the machine MAC
address as default identifier
+ host_identifier = ':'.join(("%012X" % get_mac())[i:i + 2] for i in
range(0, 12, 2))
+ if not use_host_identifier: # in case of the user sets the
host_identifier but not the use_host_identifier flag
+ host_identifier = None
+
# WARNING The initiation order must be this!!!
iotlogger.init_logging() # init logging context
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list