1 /* 2 This file is part of GNU APL, a free implementation of the 3 ISO/IEC Standard 13751, "Programming Language APL, Extended" 4 5 Copyright (C) 2008-2015 Dr. Jürgen Sauermann 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef __SVAR_DB_HH_DEFINED__ 22 #define __SVAR_DB_HH_DEFINED__ 23 24 #include <stdint.h> 25 #include <unistd.h> 26 27 #include <iostream> 28 #include <vector> 29 30 #include "Common.hh" 31 #include "ProcessorID.hh" 32 #include "Svar_record.hh" 33 34 using namespace std; 35 36 #if APSERVER_TRANSPORT == 1 37 # define ABSTRACT_OFFSET 1 38 #else 39 # define ABSTRACT_OFFSET 0 40 #endif 41 42 //----------------------------------------------------------------------------- 43 /// a pointer to one record (one shared variable) of the shared Svar_DB_memory 44 class Svar_record_P 45 { 46 public: 47 /// constructor: fetch record with key \b key from APserver 48 Svar_record_P(SV_key key); 49 50 /// return pointer to the record (overloaded -> operator) operator ->() const51 const Svar_record * operator->() const 52 { return &cache; } 53 54 protected: 55 /// the last fetched record 56 static Svar_record cache; 57 58 private: 59 /// don't copy... 60 Svar_record_P(const Svar_record_P & other); 61 62 /// don't copy... 63 Svar_record_P & operator =(const Svar_record_P & other); 64 }; 65 //----------------------------------------------------------------------------- 66 # define READ_RECORD(key, open_act, closed_act) \ 67 if (Svar_DB::APserver_available()) \ 68 { const Svar_record_P svar(key); open_act } \ 69 else { closed_act } 70 71 /// Access to the shared variable database in APserver 72 class Svar_DB 73 { 74 public: 75 /// open (and possibly initialize) the shared variable database 76 static void init(const char * bin_path, const char * prog, int retry_max, 77 bool logit, bool do_svars); 78 79 /// open (and possibly initialize) the shared variable database 80 void open_shared_memory(const char * progname, bool logit, bool do_svars); 81 82 /// match a new offer against the DB. Return: 0 on error, 1 if the 83 /// new offer was inserted into the DB (sicne no match was found), or 84 /// 2 if a pending offer was found. In the latter case, the pending offer 85 /// was removed and its relevant data returned through the d_... args. 86 static SV_key match_or_make(const uint32_t * UCS_varname, 87 const AP_num3 & to, const Svar_partner & from); 88 89 /// return true if \b id is registered in APserver 90 static bool is_registered_id(const AP_num3 & id); 91 92 /// get TCP socket to APserver, complain if not connected 93 static TCP_socket get_Svar_DB_tcp(const char * calling_function); 94 95 /// retract an offer, return previous coupling 96 static void retract_var(SV_key key); 97 98 /// return pointer to varname or 0 if key does not exist get_svar_name(SV_key key)99 static const uint32_t * get_svar_name(SV_key key) 100 { 101 READ_RECORD(key, return svar->get_svar_name(); , return 0; ) 102 } 103 104 /// find ID of the procesdsor that has offered the variable with key \b key 105 static AP_num3 find_offering_id(SV_key key); 106 107 /// add processors with pending offers to \b to_proc. Duplicates 108 /// are OK and will be removed later 109 static void get_offering_processors(AP_num to_proc, 110 std::vector<AP_num> & processors); 111 112 /// return all variables shared between \b to_proc and \b from_proc 113 static void get_offered_variables(AP_num to_proc, AP_num from_proc, 114 std::vector<uint32_t> & varnames); 115 116 /// return coupling of \b entry with \b key. get_coupling(SV_key key)117 static SV_Coupling get_coupling(SV_key key) 118 { 119 READ_RECORD(key, return svar->get_coupling(); , return NO_COUPLING;) 120 } 121 122 /// return the current control vector of this variable get_control(SV_key key)123 static Svar_Control get_control(SV_key key) 124 { 125 READ_RECORD(key, return svar->get_control(); , return NO_SVAR_CONTROL; ) 126 } 127 128 /// set the current control vector of this variable 129 static void set_control(SV_key key, Svar_Control ctl); 130 131 /// return the current state of this variable get_state(SV_key key)132 static Svar_state get_state(SV_key key) 133 { 134 READ_RECORD(key, return svar->get_state(); , return SVS_NOT_SHARED; ) 135 } 136 137 /// true if key is shared between workspaces (as opposed to shared between 138 /// a workspace and an AP is_ws_to_ws(SV_key key)139 static bool is_ws_to_ws(SV_key key) 140 { 141 READ_RECORD(key, return svar->is_ws_to_ws(); , return false; ) 142 } 143 144 /// return true iff setting the shared variable is allowed 145 static bool may_set(SV_key key, int attempt); 146 147 /// return true iff reading the shared variable is allowed 148 static bool may_use(SV_key key, int attempt); 149 150 /// set the current state of this variable 151 static void set_state(SV_key key, bool used, const char * loc); 152 153 /// some shared variables names belong to a pair, like CTL and DAT in AP210. 154 /// return the key of the other variable 155 static SV_key find_pairing_key(SV_key key); 156 157 /// clear all events, return the current event bitmap. 158 static Svar_event clear_all_events(AP_num3 id); 159 160 /// return events for processor \b proc 161 static SV_key get_events(Svar_event & events, AP_num3 proc); 162 163 /// set an event for proc (and maybe also for key) 164 static void add_event(SV_key key, AP_num3 id, Svar_event event); 165 166 /// print the database 167 static void print(ostream & out); 168 169 /// return a socket that is connect to APserver 170 static TCP_socket connect_to_APserver(const char * bin_path, 171 const char * prog, int retry_max, 172 bool logit); 173 174 /// close TCP connection to APserver disconnect()175 static void disconnect() 176 { 177 if (DB_tcp != NO_TCP_SOCKET) 178 { ::close(DB_tcp); DB_tcp = NO_TCP_SOCKET; } 179 } 180 181 /// return true if the connection to APserver is up APserver_available()182 static bool APserver_available() 183 { return DB_tcp != NO_TCP_SOCKET; } 184 185 /// return the fd towards APserver get_DB_tcp()186 static TCP_socket get_DB_tcp() 187 { return DB_tcp; } 188 189 /// print TCP error information 190 static void DB_tcp_error(const char * op, int got, int expected); 191 192 protected: 193 /// start an APserver process, return true on failure 194 static bool start_APserver(const char * server_sockname, 195 const char * bin_dir, bool logit); 196 197 /// the TCP connection to APserver, NO_TCP_SOCKET if invalid 198 static TCP_socket DB_tcp; 199 200 /// The TCP port of APserver 201 static uint16_t APserver_port; 202 203 private: 204 /// don't create... 205 Svar_DB(); 206 207 /// don't copy... 208 Svar_DB(const Svar_DB & other); 209 210 /// don't copy... 211 Svar_DB& operator =(const Svar_DB & other); 212 }; 213 214 #endif // __SVAR_DB_HH_DEFINED__ 215