Line data Source code
1 : /* File: data_change_notifier.c; Copyright and License: see below */ 2 : 3 : #include "entity/data_id.h" 4 : #include "storage/data_change_notifier.h" 5 : #include "storage/data_change_message.h" 6 : #include "u8/u8_trace.h" 7 : #include "u8/u8_log.h" 8 : #include <glib-object.h> 9 : #include <string.h> 10 : #include <assert.h> 11 : 12 : static bool data_change_notifier_glib_signal_initialized = false; 13 : static guint data_change_notifier_glib_signal_id = 0; 14 : const char *DATA_CHANGE_NOTIFIER_GLIB_SIGNAL_NAME = "cfu_data_changed"; 15 : 16 66 : void data_change_notifier_init ( data_change_notifier_t *this_ ) 17 : { 18 66 : U8_TRACE_BEGIN(); 19 : 20 66 : (*this_).num_listeners = 0; 21 66 : memset( (*this_).listener_array, '\0', sizeof( (*this_).listener_array ) ); 22 66 : (*this_).stealth_mode = false; 23 : 24 : /* define a new signal */ 25 66 : if ( ! data_change_notifier_glib_signal_initialized ) 26 : { 27 1 : data_change_notifier_glib_signal_id = g_signal_new ( 28 : DATA_CHANGE_NOTIFIER_GLIB_SIGNAL_NAME, 29 : G_TYPE_OBJECT, 30 : G_SIGNAL_RUN_FIRST, 31 : 0, 32 : NULL, 33 : NULL, 34 : g_cclosure_marshal_VOID__POINTER, 35 : G_TYPE_NONE, 36 : 1, 37 : G_TYPE_POINTER /* data_id_t*: id of the record that was created, updated or deleted */ 38 : ); 39 1 : data_change_notifier_glib_signal_initialized = true; 40 1 : U8_TRACE_INFO_INT( "g_signal_new(\"cfu_data_changed\") returned new signal id", data_change_notifier_glib_signal_id ); 41 : } 42 : 43 66 : U8_TRACE_END(); 44 66 : } 45 : 46 66 : void data_change_notifier_destroy ( data_change_notifier_t *this_ ) 47 : { 48 66 : U8_TRACE_BEGIN(); 49 : 50 66 : U8_TRACE_END(); 51 66 : } 52 : 53 2879 : void data_change_notifier_emit_signal ( data_change_notifier_t *this_, 54 : data_change_event_type_t event_type, 55 : data_table_t table, 56 : data_row_id_t row_id, 57 : data_table_t parent_table, 58 : data_row_id_t parent_row_id ) 59 : { 60 2879 : U8_TRACE_BEGIN(); 61 : 62 2879 : if ( (*this_).stealth_mode ) 63 : { 64 8 : U8_TRACE_INFO( "stealth mode: no signal sent" ); 65 : } 66 : else 67 : { 68 : /* prepare */ 69 : data_id_t modified_element_id; 70 : data_id_t parent_element_id; 71 : data_change_message_t message; 72 : 73 2871 : data_id_init( &modified_element_id, table, row_id ); 74 2871 : data_id_init( &parent_element_id, parent_table, parent_row_id ); 75 2871 : data_change_message_init( &message, 76 : event_type, 77 : modified_element_id, 78 : parent_element_id 79 : ); 80 : 81 2871 : data_change_message_trace( &message ); 82 : 83 : /* send messages */ 84 2871 : for ( int32_t pos = 0; pos < (*this_).num_listeners; pos ++ ) 85 : { 86 0 : U8_TRACE_INFO_INT( "g_signal_emit to listener", pos ); 87 0 : g_signal_emit( (*this_).listener_array[pos], data_change_notifier_glib_signal_id, 0, &message ); 88 : } 89 : 90 : /* clean up */ 91 2871 : data_id_destroy( &modified_element_id ); 92 2871 : data_id_destroy( &parent_element_id ); 93 2871 : data_change_message_destroy( &message ); 94 : } 95 : 96 2879 : U8_TRACE_END(); 97 2879 : } 98 : 99 52 : u8_error_t data_change_notifier_add_listener ( data_change_notifier_t *this_, GObject *new_listener ) 100 : { 101 52 : U8_TRACE_BEGIN(); 102 52 : assert( NULL != new_listener ); 103 52 : u8_error_t result = U8_ERROR_NONE; 104 : 105 : /* check for duplicates */ 106 52 : bool duplicate = false; 107 1231 : for ( int32_t pos = 0; pos < (*this_).num_listeners; pos ++ ) 108 : { 109 1179 : if( new_listener == (*this_).listener_array[pos] ) 110 : { 111 1 : duplicate = true; 112 1 : result = U8_ERROR_INVALID_REQUEST; 113 1 : U8_LOG_ERROR( "duplicate call to data_change_notifier_add_listener for same listener." ); 114 : } 115 : } 116 : 117 : /* if not a duplicate */ 118 52 : if ( ! duplicate ) { 119 51 : if ( (*this_).num_listeners + 1 <= DATA_CHANGE_NOTIFIER_MAX_LISTENERS ) 120 : { 121 50 : (*this_).listener_array[(*this_).num_listeners] = new_listener; /* possibly increases reference count */ 122 50 : (*this_).num_listeners ++; 123 : } 124 : else 125 : { 126 1 : result = U8_ERROR_ARRAY_BUFFER_EXCEEDED; 127 1 : U8_LOG_ERROR( "data_change_notifier_add_listener has too many listeners." ); 128 : } 129 : } 130 : 131 52 : U8_TRACE_END_ERR( result ); 132 52 : return result; 133 : } 134 : 135 54 : u8_error_t data_change_notifier_remove_listener ( data_change_notifier_t *this_, GObject *no_listener ) 136 : { 137 54 : U8_TRACE_BEGIN(); 138 54 : assert( NULL != no_listener ); 139 54 : u8_error_t result = U8_ERROR_NONE; 140 : 141 : /* search listener to remove */ 142 54 : int32_t found_at_pos = -1; /* -1 means: not found */ 143 1236 : for ( int32_t pos = 0; pos < (*this_).num_listeners; pos ++ ) 144 : { 145 1182 : if( no_listener == (*this_).listener_array[pos] ) 146 : { 147 50 : found_at_pos = pos; 148 : } 149 : } 150 : 151 : /* remove if found */ 152 54 : if ( found_at_pos != -1 ) { 153 50 : U8_TRACE_INFO_INT( "unsubscribing from pos", found_at_pos ); 154 50 : (*this_).listener_array[found_at_pos] = NULL; 155 50 : if ( found_at_pos + 1 != (*this_).num_listeners ) 156 : { 157 24 : (*this_).listener_array[found_at_pos] = (*this_).listener_array[(*this_).num_listeners-1]; 158 24 : (*this_).listener_array[(*this_).num_listeners-1] = NULL; 159 : } 160 50 : (*this_).num_listeners --; 161 : } 162 : else 163 : { 164 4 : result = U8_ERROR_INVALID_REQUEST; 165 4 : U8_LOG_ERROR( "data_change_notifier_remove_listener did not find listener to remove." ); 166 : } 167 : 168 54 : U8_TRACE_END_ERR( result ); 169 54 : return result; 170 : } 171 : 172 : 173 : /* 174 : Copyright 2016-2024 Andreas Warnke 175 : 176 : Licensed under the Apache License, Version 2.0 (the "License"); 177 : you may not use this file except in compliance with the License. 178 : You may obtain a copy of the License at 179 : 180 : http://www.apache.org/licenses/LICENSE-2.0 181 : 182 : Unless required by applicable law or agreed to in writing, software 183 : distributed under the License is distributed on an "AS IS" BASIS, 184 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 185 : See the License for the specific language governing permissions and 186 : limitations under the License. 187 : */