From 5d775d64bdec554b9842823bd1c46263210425fd Mon Sep 17 00:00:00 2001 From: Vasilii Chernov Date: Tue, 1 Mar 2016 10:42:40 +0100 Subject: 1. multithreading: - Enable multiprocessing for api_server - Enable mutrithreading for html_server 2. py: - extract pcilib->py bases from pcilib->py functions - add api for interact directly with pcilib->py without pcilib context. 3. pcipywrap - Add scripts handling. --- pywrap/CMakeLists.txt | 2 +- pywrap/api_server.py | 516 +++++++++++++++++++++++++++++++++++++++++++++++ pywrap/pcipywrap.c | 333 +++++++++++++++++++------------ pywrap/pcipywrap.h | 15 ++ pywrap/pcipywrap.i | 3 + pywrap/server.py | 539 -------------------------------------------------- 6 files changed, 743 insertions(+), 665 deletions(-) create mode 100644 pywrap/api_server.py delete mode 100644 pywrap/server.py (limited to 'pywrap') diff --git a/pywrap/CMakeLists.txt b/pywrap/CMakeLists.txt index b00fdb0..4f38354 100644 --- a/pywrap/CMakeLists.txt +++ b/pywrap/CMakeLists.txt @@ -25,6 +25,6 @@ install(TARGETS ${SWIG_MODULE_pcipywrap_REAL_NAME} DESTINATION ${PYTHON_SITE_PAC install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pcipywrap.py DESTINATION ${PYTHON_SITE_PACKAGES}) if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/server.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/api_server.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_pcipywrap.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) endif(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) diff --git a/pywrap/api_server.py b/pywrap/api_server.py new file mode 100644 index 0000000..da3a275 --- /dev/null +++ b/pywrap/api_server.py @@ -0,0 +1,516 @@ +import os +import sys + +import pcipywrap + +import time +import json +from optparse import OptionParser + +from multiprocessing import Process, current_process +from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler + +class PcilibServerHandler(BaseHTTPRequestHandler): + + def __init__(s, pcilib, *args): + s.pcilib = pcilib + BaseHTTPRequestHandler.__init__(s, *args) + + def do_HEAD(s): + s.send_response(200) + s.send_header('content-type', 'application/json') + s.end_headers() + + def do_GET(s): + length = int(s.headers['Content-Length']) + + #deserialize input data + data = json.loads(s.rfile.read(length).decode('utf-8')) + + if 'command' in data: + command = data['command'] + if(command == 'help'): + s.help(data) + + + + #elif(command == 'open'): + # #check required arguments + # if not 'device' in data: + # s.error('message doesnt contains "device" field, ' + # 'which is required for "open" command', data) + # return + # #parse command arguments and convert them to string + # device = str(data.get('device', None)) + # model = data.get('model', None) + # if not model is None: + # model = str(model) + # + # try: + # s.openPcilibInstance(device, model) + # except Exception as e: + # s.error(str(e), data) + # return + # + # #Success! Create and send reply + # out = dict() + # out['status'] = 'ok' + # s.wrapMessageAndSend(out, data) + + + + elif(command == 'get_registers_list'): + #parse command arguments and convert them to string + bank = data.get('bank', None) + if not bank is None: + bank = str(bank) + + registers = dict() + try: + registers = s.pcilib.get_registers_list(bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['registers'] = registers + s.wrapMessageAndSend(out, data) + + + + elif(command == 'get_register_info'): + #check required arguments + if not 'reg' in data: + s.error('message doesnt contains "reg" field, ' + 'which is required for "get_register_info" command', data) + return + + #parse command arguments and convert them to string + reg = str(data.get('reg', None)) + bank = data.get('bank', None) + if not bank is None: + bank = str(bank) + + register = dict() + try: + register = s.pcilib.get_register_info(reg, bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok', 'register': register}, data) + + + + elif(command == 'get_property_list'): + #parse command arguments and convert them to string + branch = data.get('branch', None) + if not branch is None: + branch = str(branch) + + properties = dict() + try: + properties = s.pcilib.get_property_list(branch) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['properties'] = properties + s.wrapMessageAndSend(out, data) + + + + elif(command == 'read_register'): + #check required arguments + if not 'reg' in data: + s.error('message doesnt contains "reg" field, ' + 'which is required for "read_register" command', data) + return + + #parse command arguments and convert them to string + reg = str(data.get('reg', None)) + bank = data.get('bank', None) + if not bank is None: + bank = str(bank) + + value = 0 + try: + value = s.pcilib.read_register(reg, bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['value'] = value + s.wrapMessageAndSend(out, data) + + + + elif(command == 'write_register'): + #check required arguments + if not 'reg' in data: + s.error('message doesnt contains "reg" field, ' + 'which is required for "write_register" command', data) + return + + if not 'value' in data: + s.error('message doesnt contains "value" field, ' + 'which is required for "write_register" command', data) + return + + #parse command arguments and convert them to string + reg = str(data.get('reg', None)) + value = str(data.get('value', None)) + bank = data.get('bank', None) + if not bank is None: + bank = str(bank) + + try: + s.pcilib.write_register(value, reg, bank) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'get_property'): + #check required arguments + if not 'prop' in data: + s.error('message doesnt contains "prop" field, ' + 'which is required for "get_property" command', data) + return + + #parse command arguments and convert them to string + prop = str(data.get('prop', None)) + + value = 0 + try: + value = s.pcilib.get_property(prop) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + out = dict() + out['status'] = 'ok' + out['value'] = value + s.wrapMessageAndSend(out, data) + + + + elif(command == 'set_property'): + #check required arguments + if not 'prop' in data: + s.error('message doesnt contains "prop" field, ' + 'which is required for "set_property" command', data) + return + + if not 'value' in data: + s.error('message doesnt contains "value" field, ' + 'which is required for "set_property" command', data) + return + + #parse command arguments and convert them to string + prop = str(data.get('prop', None)) + value = str(data.get('value', None)) + + try: + s.pcilib.set_property(value, prop) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'lock'): + #check required arguments + if not 'lock_id' in data: + s.error('message doesnt contains "lock_id" field, ' + 'which is required for "lock" command', data) + return + + #parse command arguments and convert them to string + lock_id = str(data.get('lock_id')) + + try: + s.pcilib.lock(lock_id) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'try_lock'): + #check required arguments + if not 'lock_id' in data: + s.error('message doesnt contains "lock_id" field, ' + 'which is required for "try_lock" command', data) + return + + #parse command arguments and convert them to string + lock_id = str(data.get('lock_id')) + + try: + s.pcilib.try_lock(lock_id) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + elif(command == 'unlock'): + #check required arguments + if not 'lock_id' in data: + s.error('message doesnt contains "lock_id" field, ' + 'which is required for "unlock" command', data) + return + + #parse command arguments and convert them to string + lock_id = str(data.get('lock_id')) + + try: + print 'unlocking ' + lock_id + s.pcilib.unlock(lock_id) + except Exception as e: + s.error(str(e), data) + return + + #Success! Create and send reply + s.wrapMessageAndSend({'status': 'ok'}, data) + + + + #elif(command == 'lock_global'): + # #check if global_lock already setted by server + # try: + # s.pcilib.lock_global() + # except Exception as e: + # s.error(str(e), data) + # return + # + # #Success! Create and send reply + # s.wrapMessageAndSend({'status': 'ok'}, data) + + + + #elif(command == 'unlock_global'): + # try: + # s.pcilib.unlock_global() + # except Exception as e: + # s.error(str(e), data) + # return + # + # #Success! Create and send reply + # s.wrapMessageAndSend({'status': 'ok'}, data) + + + + else: + s.error('command "' + command + '" undefined', data) + return + else: + s.error('message doesnt contains "command" field, which is required', data) + return + + + #print str(s.headers['content-type']) + #print post_data['some'] + + #open device context + #def openPcilibInstance(s, device, model): + # s.pcilib = pcipywrap.create_pcilib_instance(device, model) + + #Send help message + def help(s, received_message = None): + usage = str('Usage:\n' + ' Server receive commands via http GET with json packet.\n' + ' content-type should have value "application/json"\n' + ' Server could handle only commands. to set command, you\n' + ' should specify field "command" in packet with command name\n' + ' List of commands:\n' + '\n' + ' command: help - Get help. This will return usage\n' + '\n' + + ' command: open - Opens context of device. It will be reopened if already open.\n' + ' required fields\n' + ' device: - path to the device file [/dev/fpga0]\n' + ' optional fields\n' + ' model: - specifies the model of hardware, autodetected if doesnt exists\n' + '\n' + + ' command: get_registers_list - Returns the list of registers provided by the hardware model.\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be returned\n' + '\n' + + ' command: get_register_info - Returns the information about the specified register.\n' + ' required fields\n' + ' reg: - the name of the register\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be returned\n' + '\n' + + ' command: get_property_list - Returns the list of properties available under the specified path.\n' + ' optional fields\n' + ' branch: - Path. If not set, will return the top-level properties\n' + '\n' + + ' command: read_register - Reads the specified register.\n' + ' required fields\n' + ' reg: - the name of the register\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be processed\n' + '\n' + + ' command: write_register - Writes to specified register.\n' + ' required fields\n' + ' reg: - the name of the register\n' + ' value: - the register value to write. Should be int, float or string (with number)\n' + ' optional fields\n' + ' bank: - if set, only register within the specified bank will be processed\n' + '\n' + + ' command: get_property - Reads / computes the property value.\n' + ' required fields\n' + ' prop: - full name including path\n' + '\n' + + ' command: set_property - Writes the property value or executes the code associated with property.\n' + ' required fields\n' + ' prop: - full name including path\n' + ' value: - the property value to write. Should be int, float or string (with number)\n' + '\n' + + ' command: lock - function to acquire a lock, and wait till the lock can be acquire.\n' + ' required fields\n' + ' lock_id: - lock id\n' + '\n' + + ' command: try_lock - this function will try to take a lock for the mutex pointed by \n' + ' lockfunction to acquire a lock, but that returns immediatly if the\n' + ' lock can\'t be acquired on first try\n' + ' lock_id: - lock id\n' + '\n' + + ' command: unlock - this function unlocks the lock.\n' + ' required fields\n' + ' lock_id: - lock id\n' + '\n' + + '\n') + out = {'status': 'ok', 'usage' : usage} + s.wrapMessageAndSend(out, received_message) + + #Send error message with text description + def error(s, info, received_message = None): + out = dict() + + out['status'] = 'error' + out['description'] = info + out['note'] = 'send {"command" : "help"} to get help' + s.wrapMessageAndSend(out, received_message, 400) + + def wrapMessageAndSend(s, message, received_message = None, response = 200): + s.send_response(response) + s.send_header('content-type', 'application/json') + s.end_headers() + if not received_message is None: + message['received_message'] = received_message + s.wfile.write(json.dumps(message)) + +def serve_forever(server): + try: + server.serve_forever() + except KeyboardInterrupt: + pass + +def runpool(server, number_of_processes): + # create child processes to act as workers + for i in range(number_of_processes-1): + Process(target=serve_forever, args=(server,)).start() + + # main process also acts as a worker + serve_forever(server) + +if __name__ == '__main__': + + #parce command line options + parser = OptionParser() + parser.add_option("-p", "--port", action="store", + type="int", dest="port", default=9000, + help="Set server port (9000)") + parser.add_option("-d", "--device", action="store", + type="string", dest="device", default=str('/dev/fpga0'), + help="FPGA device (/dev/fpga0)") + parser.add_option("-m", "--model", action="store", + type="string", dest="model", default=None, + help="Memory model (autodetected)") + parser.add_option("-n", "--number_processes", action="store", + type="int", dest="processes", default=4, + help="Number of processes, used by server (4)") + opts = parser.parse_args()[0] + + HOST_NAME = '' + PORT_NUMBER = opts.port + MODEL = opts.model + DEVICE = opts.device + + + + #Set enviroment variables, if it not setted already + if not 'APP_PATH' in os.environ: + APP_PATH = '' + file_dir = os.path.dirname(os.path.abspath(__file__)) + APP_PATH = str(os.path.abspath(file_dir + '/../..')) + os.environ["APP_PATH"] = APP_PATH + + if not 'PCILIB_MODEL_DIR' in os.environ: + os.environ['PCILIB_MODEL_DIR'] = os.environ["APP_PATH"] + "/xml" + + if not 'LD_LIBRARY_PATH' in os.environ: + os.environ['LD_LIBRARY_PATH'] = os.environ["APP_PATH"] + "/pcilib" + + + + #redirect logs to exeption + pcipywrap.__redirect_logs_to_exeption() + + #pass Pcipywrap to to server handler + global pcilib + lib = pcipywrap.Pcipywrap(DEVICE, MODEL) + def handler(*args): + PcilibServerHandler(lib, *args) + + #start server + httpd = HTTPServer((HOST_NAME, PORT_NUMBER), handler) + runpool(httpd, opts.processes) + + print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER) + #try: + # httpd.serve_forever() + #except KeyboardInterrupt: + # pass + + httpd.server_close() + print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER) diff --git a/pywrap/pcipywrap.c b/pywrap/pcipywrap.c index 391bdf4..cfb4e53 100644 --- a/pywrap/pcipywrap.c +++ b/pywrap/pcipywrap.c @@ -1,6 +1,9 @@ #include "pcipywrap.h" #include "locking.h" +#include +#include + char* full_log = NULL; /*! @@ -101,27 +104,6 @@ void __redirect_logs_to_exeption() pcilib_get_logger_context()); } -/*! - * \brief Wrap for PyDict_SetItem, with decrease reference counting after set. - */ -void pcilib_pydict_set_item(PyObject* dict, PyObject* name, PyObject* value) -{ - PyDict_SetItem(dict, - name, - value); - Py_XDECREF(name); - Py_XDECREF(value); -} - -/*! - * \brief Wrap for PyList_Append, with decrease reference counting after append. - */ -void pcilib_pylist_append(PyObject* list, PyObject* value) -{ - PyList_Append(list, value); - Py_XDECREF(value); -} - void add_pcilib_value_to_dict(pcilib_t* ctx, PyObject* dict, pcilib_value_t* val, const char *name) { PyObject *py_val = (PyObject*)pcilib_get_value_as_pyobject(ctx, val, NULL); @@ -215,126 +197,198 @@ PyObject * pcilib_convert_property_info_to_pyobject(pcilib_t* ctx, pcilib_proper PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_register_info_t listItem) { - PyObject* pylistItem = PyDict_New(); - - if(listItem.name) - pcilib_pydict_set_item(pylistItem, - PyString_FromString("name"), - PyString_FromString(listItem.name)); - - if(listItem.description) - pcilib_pydict_set_item(pylistItem, - PyString_FromString("description"), - PyString_FromString(listItem.description)); - - if(listItem.bank) - pcilib_pydict_set_item(pylistItem, - PyString_FromString("bank"), - PyString_FromString(listItem.bank)); - - - //serialize modes - PyObject* modes = PyList_New(0); - - if((listItem.mode & PCILIB_REGISTER_R) == PCILIB_REGISTER_R) - pcilib_pylist_append(modes, PyString_FromString("R")); - if((listItem.mode & PCILIB_REGISTER_W) == PCILIB_REGISTER_W) - pcilib_pylist_append(modes, PyString_FromString("W")); - if((listItem.mode & PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW) - pcilib_pylist_append(modes, PyString_FromString("RW")); - if((listItem.mode & PCILIB_REGISTER_W1C) == PCILIB_REGISTER_W1C) - pcilib_pylist_append(modes, PyString_FromString("W1C")); - if((listItem.mode & PCILIB_REGISTER_RW1C) == PCILIB_REGISTER_RW1C) - pcilib_pylist_append(modes, PyString_FromString("RW1C")); - if((listItem.mode & PCILIB_REGISTER_W1I) == PCILIB_REGISTER_W1I) - pcilib_pylist_append(modes, PyString_FromString("W1I")); - if((listItem.mode & PCILIB_REGISTER_RW1I) == PCILIB_REGISTER_RW1I) - pcilib_pylist_append(modes, PyString_FromString("RW1I")); - if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT) - pcilib_pylist_append(modes, PyString_FromString("NO_CHK")); - - pcilib_pydict_set_item(pylistItem, - PyString_FromString("mode"), - modes); - - pcilib_value_t defval = {0}; - pcilib_set_value_from_register_value(ctx, &defval, listItem.defvalue); - add_pcilib_value_to_dict(ctx, pylistItem, &defval, "defvalue"); - - if(listItem.range) - { - pcilib_value_t minval = {0}; - pcilib_set_value_from_register_value(ctx, &minval, listItem.range->min); - - pcilib_value_t maxval = {0}; - pcilib_set_value_from_register_value(ctx, &maxval, listItem.range->max); - - PyObject* range = PyDict_New(); - add_pcilib_value_to_dict(ctx, range, &minval, "min"); - add_pcilib_value_to_dict(ctx, range, &maxval, "max"); - pcilib_pydict_set_item(pylistItem, - PyString_FromString("range"), - range); - } - - if(listItem.values) - { + PyObject* pylistItem = PyDict_New(); + + if(listItem.name) + pcilib_pydict_set_item(pylistItem, + PyString_FromString("name"), + PyString_FromString(listItem.name)); + + if(listItem.description) + pcilib_pydict_set_item(pylistItem, + PyString_FromString("description"), + PyString_FromString(listItem.description)); + + if(listItem.bank) + pcilib_pydict_set_item(pylistItem, + PyString_FromString("bank"), + PyString_FromString(listItem.bank)); + + + //serialize modes + PyObject* modes = PyList_New(0); + + if((listItem.mode & PCILIB_REGISTER_R) == PCILIB_REGISTER_R) + pcilib_pylist_append(modes, PyString_FromString("R")); + if((listItem.mode & PCILIB_REGISTER_W) == PCILIB_REGISTER_W) + pcilib_pylist_append(modes, PyString_FromString("W")); + if((listItem.mode & PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW) + pcilib_pylist_append(modes, PyString_FromString("RW")); + if((listItem.mode & PCILIB_REGISTER_W1C) == PCILIB_REGISTER_W1C) + pcilib_pylist_append(modes, PyString_FromString("W1C")); + if((listItem.mode & PCILIB_REGISTER_RW1C) == PCILIB_REGISTER_RW1C) + pcilib_pylist_append(modes, PyString_FromString("RW1C")); + if((listItem.mode & PCILIB_REGISTER_W1I) == PCILIB_REGISTER_W1I) + pcilib_pylist_append(modes, PyString_FromString("W1I")); + if((listItem.mode & PCILIB_REGISTER_RW1I) == PCILIB_REGISTER_RW1I) + pcilib_pylist_append(modes, PyString_FromString("RW1I")); + if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT) + pcilib_pylist_append(modes, PyString_FromString("NO_CHK")); + + pcilib_pydict_set_item(pylistItem, + PyString_FromString("mode"), + modes); + + pcilib_value_t defval = {0}; + pcilib_set_value_from_register_value(ctx, &defval, listItem.defvalue); + add_pcilib_value_to_dict(ctx, pylistItem, &defval, "defvalue"); + + if(listItem.range) + { + pcilib_value_t minval = {0}; + pcilib_set_value_from_register_value(ctx, &minval, listItem.range->min); + + pcilib_value_t maxval = {0}; + pcilib_set_value_from_register_value(ctx, &maxval, listItem.range->max); + + PyObject* range = PyDict_New(); + add_pcilib_value_to_dict(ctx, range, &minval, "min"); + add_pcilib_value_to_dict(ctx, range, &maxval, "max"); + pcilib_pydict_set_item(pylistItem, + PyString_FromString("range"), + range); + } - PyObject* values = PyList_New(0); + if(listItem.values) + { - for (int j = 0; listItem.values[j].name; j++) - { - PyObject* valuesItem = PyDict_New(); + PyObject* values = PyList_New(0); - pcilib_value_t val = {0}; - pcilib_set_value_from_register_value(ctx, &val, listItem.values[j].value); + for (int j = 0; listItem.values[j].name; j++) + { + PyObject* valuesItem = PyDict_New(); - pcilib_value_t min = {0}; - pcilib_set_value_from_register_value(ctx, &min, listItem.values[j].min); + pcilib_value_t val = {0}; + pcilib_set_value_from_register_value(ctx, &val, listItem.values[j].value); - pcilib_value_t max = {0}; - pcilib_set_value_from_register_value(ctx, &max, listItem.values[j].max); + pcilib_value_t min = {0}; + pcilib_set_value_from_register_value(ctx, &min, listItem.values[j].min); - add_pcilib_value_to_dict(ctx, valuesItem, &val, "value"); - add_pcilib_value_to_dict(ctx, valuesItem, &min, "min"); - add_pcilib_value_to_dict(ctx, valuesItem, &max, "max"); + pcilib_value_t max = {0}; + pcilib_set_value_from_register_value(ctx, &max, listItem.values[j].max); - if(listItem.values[j].name) - pcilib_pydict_set_item(valuesItem, - PyString_FromString("name"), - PyString_FromString(listItem.values[j].name)); - if(listItem.values[j].description) - { - pcilib_pydict_set_item(valuesItem, - PyString_FromString("description"), - PyString_FromString(listItem.values[j].description)); + add_pcilib_value_to_dict(ctx, valuesItem, &val, "value"); + add_pcilib_value_to_dict(ctx, valuesItem, &min, "min"); + add_pcilib_value_to_dict(ctx, valuesItem, &max, "max"); - } - pcilib_pylist_append(values, valuesItem); - } + if(listItem.values[j].name) + pcilib_pydict_set_item(valuesItem, + PyString_FromString("name"), + PyString_FromString(listItem.values[j].name)); + if(listItem.values[j].description) + { + pcilib_pydict_set_item(valuesItem, + PyString_FromString("description"), + PyString_FromString(listItem.values[j].description)); - pcilib_pydict_set_item(pylistItem, - PyString_FromString("values"), - values); - } + } + pcilib_pylist_append(values, valuesItem); + } - return pylistItem; + pcilib_pydict_set_item(pylistItem, + PyString_FromString("values"), + values); + } + return pylistItem; } + Pcipywrap *new_Pcipywrap(const char* fpga_device, const char* model) { //opening device pcilib_t* ctx = pcilib_open(fpga_device, model); - if(!ctx) - { + if(!ctx) { set_python_exception("Failed pcilib_open(%s, %s)", fpga_device, model); return NULL; } + Pcipywrap *self; self = (Pcipywrap *) malloc(sizeof(Pcipywrap)); + if(!self) { + pcilib_close(ctx); + return (Pcipywrap *)PyExc_MemoryError; + } self->shared = 0; self->ctx = ctx; + self->py = NULL; + self->names = NULL; + self->names_size = 0; + + + //processing pcilib scrips + const char *scripts_dir = getenv("PCILIB_SCRIPTS_DIR"); + if(scripts_dir) { + int err = 0; + + self->py = pcilib_init_py_ctx(ctx->py, &err); + if(err) { + delete_Pcipywrap(self); + set_python_exception("Failed pcilib_py_s_clone (%i)", err); + return NULL; + } + + //add scripts directory to Python path + err = pcilib_py_ctx_add_script_dir(self->py, scripts_dir); + if(err) { + delete_Pcipywrap(self); + set_python_exception("Failed pcilib_py_add_dir (%i)", err); + return NULL; + } + + //load scripts in PCILIB_SCRIPTS_DIR + self->names = malloc(++(self->names_size) * sizeof(char*)); + self->names[self->names_size - 1] = NULL; + + DIR *dir; + struct dirent *script_path; + dir = opendir(scripts_dir); + if (dir) { + while ((script_path = readdir(dir)) != NULL) { + + char *py = strrchr(script_path->d_name, '.'); + if ((!py)||(strcasecmp(py, ".py"))) { + continue; + } + + char *name = malloc(strlen(script_path->d_name)); + if(!name) { + delete_Pcipywrap(self); + return (Pcipywrap *)PyExc_MemoryError; + } + + strcpy(name, script_path->d_name); + + err = pcilib_py_ctx_load_script(self->py, name); + + if(err) { + delete_Pcipywrap(self); + set_python_exception("pcilib_py_ctx_load_script (%i)", err); + return NULL; + } + + self->names = realloc(self->names, ++(self->names_size)); + if(!self->names) { + delete_Pcipywrap(self); + return (Pcipywrap *)PyExc_MemoryError; + } + self->names[self->names_size - 1] = NULL; + self->names[self->names_size - 2] = name; + } + closedir(dir); + } + } + return self; } @@ -350,14 +404,27 @@ Pcipywrap *create_Pcipywrap(PyObject* ctx) self = (Pcipywrap *) malloc(sizeof(Pcipywrap)); self->shared = 1; self->ctx = PyCObject_AsVoidPtr(ctx); + self->py = NULL; + self->names = NULL; + self->names_size = 0; return self; } void delete_Pcipywrap(Pcipywrap *self) { - if(!self->shared) - pcilib_close(self->ctx); - - free(self); + if(!self->shared) + pcilib_close(self->ctx); + + pcilib_free_py_ctx(self->py); + + if(self->names) { + for(int i = 0; self->names[i]; i++) + free(self->names[i]); + free(self->names); + self->names = NULL; + self->names_size = 0; + } + + free(self); } PyObject* Pcipywrap_read_register(Pcipywrap *self, const char *regname, const char *bank) @@ -464,7 +531,7 @@ PyObject* Pcipywrap_get_registers_list(Pcipywrap *self, const char *bank) set_python_exception("pcilib_get_register_list return NULL"); return NULL; } - + PyObject* pyList = PyList_New(0); for(int i = 0; list[i].name; i++) { @@ -554,7 +621,7 @@ void Pcipywrap_unlock_global(Pcipywrap *self) PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id) { pcilib_lock_t* lock = pcilib_get_lock(self->ctx, - PCILIB_LOCK_FLAGS_DEFAULT, + PCILIB_LOCK_FLAG_PERSISTENT, lock_id); if(!lock) { @@ -576,7 +643,7 @@ PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id) PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id) { pcilib_lock_t* lock = pcilib_get_lock(self->ctx, - PCILIB_LOCK_FLAGS_DEFAULT, + PCILIB_LOCK_FLAG_PERSISTENT, lock_id); if(!lock) { @@ -597,7 +664,7 @@ PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id) PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id) { pcilib_lock_t* lock = pcilib_get_lock(self->ctx, - PCILIB_LOCK_FLAGS_DEFAULT, + PCILIB_LOCK_FLAG_PERSISTENT, lock_id); if(!lock) { @@ -609,4 +676,20 @@ PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id) return PyInt_FromLong((long)1); } +PyObject* Pcipywrap_get_scripts_list(Pcipywrap *self) +{ + return pcilib_py_ctx_get_scripts_info(self->py); +} +PyObject* Pcipywrap_run_script(Pcipywrap *self, const char* script_name, PyObject* value) +{ + int err = 0; + PyObject* value_out = pcilib_py_ctx_eval_func(self->py, script_name, "run", value, &err); + + if(err) { + set_python_exception("Failed pcilib_py_ctx_eval_func (%i)", err); + return NULL; + } + + return value_out; +} diff --git a/pywrap/pcipywrap.h b/pywrap/pcipywrap.h index dcce245..2d9115b 100644 --- a/pywrap/pcipywrap.h +++ b/pywrap/pcipywrap.h @@ -5,11 +5,23 @@ #include "error.h" #include +#include "config.h" +#include "py.h" + +#include "pci.h" +#include "pcilib.h" + + typedef struct { + char** names; + int names_size; + void* ctx; + struct pcilib_py_s *py; int shared; } Pcipywrap; + /*! * \brief Redirect pcilib standart log stream to exeption text. * Logger will accumulate errors untill get message, starts with "#E". @@ -83,4 +95,7 @@ PyObject* Pcipywrap_lock(Pcipywrap *self, const char *lock_id); PyObject* Pcipywrap_try_lock(Pcipywrap *self, const char *lock_id); PyObject* Pcipywrap_unlock(Pcipywrap *self, const char *lock_id); +PyObject* Pcipywrap_get_scripts_list(Pcipywrap *self); +PyObject* Pcipywrap_run_script(Pcipywrap *self, const char* script_name, PyObject* value); + #endif /* PCIPYWRAP_H */ diff --git a/pywrap/pcipywrap.i b/pywrap/pcipywrap.i index f08ceb7..104e19f 100644 --- a/pywrap/pcipywrap.i +++ b/pywrap/pcipywrap.i @@ -29,5 +29,8 @@ typedef struct { PyObject* lock(const char *lock_id); PyObject* try_lock(const char *lock_id); PyObject* unlock(const char *lock_id); + + PyObject* get_scripts_list(); + PyObject* run_script(const char* script_name, PyObject* value); } } Pcipywrap; diff --git a/pywrap/server.py b/pywrap/server.py deleted file mode 100644 index b59ae55..0000000 --- a/pywrap/server.py +++ /dev/null @@ -1,539 +0,0 @@ -import time -import os -import pcipywrap -import json -import sys -from optparse import OptionParser - -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from SocketServer import ThreadingMixIn -import threading - -pcilib = None - -class MultiThreadedHTTPServer(ThreadingMixIn, HTTPServer): - pass - -class PcilibServerHandler(BaseHTTPRequestHandler): - locks = list() - lock_global = 0 - - #def __init__(s, pcilib, *args): - # s.pcilib = pcilib - # BaseHTTPRequestHandler.__init__(s, *args) - - def do_HEAD(s): - s.send_response(200) - s.send_header('content-type', 'application/json') - s.end_headers() - - def do_GET(s): - length = int(s.headers['Content-Length']) - - #deserialize input data - data = json.loads(s.rfile.read(length).decode('utf-8')) - - if 'command' in data: - command = data['command'] - if(command == 'help'): - s.help(data) - - - - #elif(command == 'open'): - # #check required arguments - # if not 'device' in data: - # s.error('message doesnt contains "device" field, ' - # 'which is required for "open" command', data) - # return - # #parse command arguments and convert them to string - # device = str(data.get('device', None)) - # model = data.get('model', None) - # if not model is None: - # model = str(model) - # - # try: - # s.openPcilibInstance(device, model) - # except Exception as e: - # s.error(str(e), data) - # return - # - # #Success! Create and send reply - # out = dict() - # out['status'] = 'ok' - # s.wrapMessageAndSend(out, data) - - - - elif(command == 'get_registers_list'): - #parse command arguments and convert them to string - bank = data.get('bank', None) - if not bank is None: - bank = str(bank) - - registers = dict() - try: - registers = pcilib.get_registers_list(bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['registers'] = registers - s.wrapMessageAndSend(out, data) - - - - elif(command == 'get_register_info'): - #check required arguments - if not 'reg' in data: - s.error('message doesnt contains "reg" field, ' - 'which is required for "get_register_info" command', data) - return - - #parse command arguments and convert them to string - reg = str(data.get('reg', None)) - bank = data.get('bank', None) - if not bank is None: - bank = str(bank) - - register = dict() - try: - register = pcilib.get_register_info(reg, bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok', 'register': register}, data) - - - - elif(command == 'get_property_list'): - #parse command arguments and convert them to string - branch = data.get('branch', None) - if not branch is None: - branch = str(branch) - - properties = dict() - try: - properties = pcilib.get_property_list(branch) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['properties'] = properties - s.wrapMessageAndSend(out, data) - - - - elif(command == 'read_register'): - #check required arguments - if not 'reg' in data: - s.error('message doesnt contains "reg" field, ' - 'which is required for "read_register" command', data) - return - - #parse command arguments and convert them to string - reg = str(data.get('reg', None)) - bank = data.get('bank', None) - if not bank is None: - bank = str(bank) - - value = 0 - try: - value = pcilib.read_register(reg, bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['value'] = value - s.wrapMessageAndSend(out, data) - - - - elif(command == 'write_register'): - #check required arguments - if not 'reg' in data: - s.error('message doesnt contains "reg" field, ' - 'which is required for "write_register" command', data) - return - - if not 'value' in data: - s.error('message doesnt contains "value" field, ' - 'which is required for "write_register" command', data) - return - - #parse command arguments and convert them to string - reg = str(data.get('reg', None)) - value = str(data.get('value', None)) - bank = data.get('bank', None) - if not bank is None: - bank = str(bank) - - try: - pcilib.write_register(value, reg, bank) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'get_property'): - #check required arguments - if not 'prop' in data: - s.error('message doesnt contains "prop" field, ' - 'which is required for "get_property" command', data) - return - - #parse command arguments and convert them to string - prop = str(data.get('prop', None)) - - value = 0 - try: - value = pcilib.get_property(prop) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - out = dict() - out['status'] = 'ok' - out['value'] = value - s.wrapMessageAndSend(out, data) - - - - elif(command == 'set_property'): - #check required arguments - if not 'prop' in data: - s.error('message doesnt contains "prop" field, ' - 'which is required for "set_property" command', data) - return - - if not 'value' in data: - s.error('message doesnt contains "value" field, ' - 'which is required for "set_property" command', data) - return - - #parse command arguments and convert them to string - prop = str(data.get('prop', None)) - value = str(data.get('value', None)) - - try: - pcilib.set_property(value, prop) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'lock'): - #check required arguments - if not 'lock_id' in data: - s.error('message doesnt contains "lock_id" field, ' - 'which is required for "lock" command', data) - return - - #parse command arguments and convert them to string - lock_id = str(data.get('lock_id')) - - #check if lock already setted - #if lock_id in PcilibServerHandler.locks: - # s.error('Lock with id: ' + lock_id + - # 'already setted by this server', - # data) - # return - - try: - pcilib.lock(lock_id) - except Exception as e: - s.error(str(e), data) - return - - PcilibServerHandler.locks.append(lock_id) - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'try_lock'): - #check required arguments - if not 'lock_id' in data: - s.error('message doesnt contains "lock_id" field, ' - 'which is required for "try_lock" command', data) - return - - #parse command arguments and convert them to string - lock_id = str(data.get('lock_id')) - - try: - pcilib.try_lock(lock_id) - except Exception as e: - s.error(str(e), data) - return - - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - elif(command == 'unlock'): - #check required arguments - #if not 'lock_id' in data: - # s.error('message doesnt contains "lock_id" field, ' - # 'which is required for "unlock" command', data) - # return - - #parse command arguments and convert them to string - #lock_id = str(data.get('lock_id')) - - #try: - # pcilib.unlock(lock_id) - #except Exception as e: - # s.error(str(e), data) - # return - # - #remove lock from locks list - #if lock_id in PcilibServerHandler.locks: - # PcilibServerHandler.locks.remove(lock_id) - time.sleep(20) - #Success! Create and send reply - s.wrapMessageAndSend({'status': 'ok'}, data) - - - - #elif(command == 'lock_global'): - # #check if global_lock already setted by server - # print 'aaa' - # if PcilibServerHandler.lock_global: - # - # s.error('global lock already setted by this server', data) - # return - # - # try: - # pcilib.lock_global() - # except Exception as e: - # s.error(str(e), data) - # return - # - # PcilibServerHandler.lock_global = 1 - # - # #Success! Create and send reply - # s.wrapMessageAndSend({'status': 'ok'}, data) - - - - #elif(command == 'unlock_global'): - # try: - # pcilib.unlock_global() - # except Exception as e: - # s.error(str(e), data) - # return - # - # PcilibServerHandler.lock_global = 0 - # - # #Success! Create and send reply - # s.wrapMessageAndSend({'status': 'ok'}, data) - - - - else: - s.error('command "' + command + '" undefined', data) - return - else: - s.error('message doesnt contains "command" field, which is required', data) - return - - - #print str(s.headers['content-type']) - #print post_data['some'] - - #"""open device context """ - #def openPcilibInstance(s, device, model): - # pcilib = pcipywrap.create_pcilib_instance(device, model) - - """Send help message""" - def help(s, received_message = None): - usage = str('Usage:\n' - ' Server receive commands via http GET with json packet.\n' - ' content-type should have value "application/json"\n' - ' Server could handle only commands. to set command, you\n' - ' should specify field "command" in packet with command name\n' - ' List of commands:\n' - '\n' - ' command: help - Get help. This will return usage\n' - '\n' - - ' command: open - Opens context of device. It will be reopened if already open.\n' - ' required fields\n' - ' device: - path to the device file [/dev/fpga0]\n' - ' optional fields\n' - ' model: - specifies the model of hardware, autodetected if doesnt exists\n' - '\n' - - ' command: get_registers_list - Returns the list of registers provided by the hardware model.\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be returned\n' - '\n' - - ' command: get_register_info - Returns the information about the specified register.\n' - ' required fields\n' - ' reg: - the name of the register\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be returned\n' - '\n' - - ' command: get_property_list - Returns the list of properties available under the specified path.\n' - ' optional fields\n' - ' branch: - Path. If not set, will return the top-level properties\n' - '\n' - - ' command: read_register - Reads the specified register.\n' - ' required fields\n' - ' reg: - the name of the register\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be processed\n' - '\n' - - ' command: write_register - Writes to specified register.\n' - ' required fields\n' - ' reg: - the name of the register\n' - ' value: - the register value to write. Should be int, float or string (with number)\n' - ' optional fields\n' - ' bank: - if set, only register within the specified bank will be processed\n' - '\n' - - ' command: get_property - Reads / computes the property value.\n' - ' required fields\n' - ' prop: - full name including path\n' - '\n' - - ' command: set_property - Writes the property value or executes the code associated with property.\n' - ' required fields\n' - ' prop: - full name including path\n' - ' value: - the property value to write. Should be int, float or string (with number)\n' - '\n' - - ' command: lock - function to acquire a lock, and wait till the lock can be acquire.\n' - ' required fields\n' - ' lock_id: - lock id\n' - '\n' - - ' command: try_lock - this function will try to take a lock for the mutex pointed by \n' - ' lockfunction to acquire a lock, but that returns immediatly if the\n' - ' lock can\'t be acquired on first try\n' - ' lock_id: - lock id\n' - '\n' - - ' command: unlock - this function unlocks the lock.\n' - ' required fields\n' - ' lock_id: - lock id\n' - '\n' - - '\n') - out = {'status': 'ok', 'usage' : usage} - s.wrapMessageAndSend(out, received_message) - - """Send error message with text description""" - def error(s, info, received_message = None): - out = dict() - - out['status'] = 'error' - out['description'] = info - out['note'] = 'send {"command" : "help"} to get help' - s.wrapMessageAndSend(out, received_message, 400) - - def wrapMessageAndSend(s, message, received_message = None, response = 200): - s.send_response(response) - s.send_header('content-type', 'application/json') - s.end_headers() - if not received_message is None: - message['received_message'] = received_message - message['thread'] = threading.currentThread().getName() - s.wfile.write(json.dumps(message)) - -if __name__ == '__main__': - - #parce command line options - parser = OptionParser() - parser.add_option("-p", "--port", action="store", - type="int", dest="port", default=9000, - help="Set server port (9000)") - parser.add_option("-d", "--device", action="store", - type="string", dest="device", default=str('/dev/fpga0'), - help="FPGA device (/dev/fpga0)") - parser.add_option("-m", "--model", action="store", - type="string", dest="model", default=None, - help="Memory model (autodetected)") - opts = parser.parse_args()[0] - - HOST_NAME = '' - PORT_NUMBER = opts.port - MODEL = opts.model - DEVICE = opts.device - - - - #Set enviroment variables, if it not setted already - if not 'APP_PATH' in os.environ: - APP_PATH = '' - file_dir = os.path.dirname(os.path.abspath(__file__)) - APP_PATH = str(os.path.abspath(file_dir + '/../..')) - os.environ["APP_PATH"] = APP_PATH - - if not 'PCILIB_MODEL_DIR' in os.environ: - os.environ['PCILIB_MODEL_DIR'] = os.environ["APP_PATH"] + "/xml" - - if not 'LD_LIBRARY_PATH' in os.environ: - os.environ['LD_LIBRARY_PATH'] = os.environ["APP_PATH"] + "/pcilib" - - - - #redirect logs to exeption - pcipywrap.__redirect_logs_to_exeption() - - #pass Pcipywrap to to server handler - global pcilib - pcilib = pcipywrap.Pcipywrap(DEVICE, MODEL) - #def handler(*args): - # PcilibServerHandler(lib, *args) - - #start server - httpd = MultiThreadedHTTPServer((HOST_NAME, PORT_NUMBER), PcilibServerHandler) - - print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER) - try: - httpd.serve_forever() - except KeyboardInterrupt: - #unlocking global lock - if PcilibServerHandler.lock_global: - lib.unlock_global() - PcilibServerHandler.lock_global = False - - #delete created locks - for lock in PcilibServerHandler.locks: - lib.unlock(lock) - del PcilibServerHandler.locks[:] - pass - - - - - httpd.server_close() - print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER) -- cgit v1.2.3