| | 112 | |
| | 113 | == VSO Specific Triggers == |
| | 114 | |
| | 115 | There are two triggers that may be installed after the subscription process |
| | 116 | |
| | 117 | === Automatic data mirroring === |
| | 118 | |
| | 119 | Sites that are using the JMD to retrieve data will have a table in their database named `sunum_queue` : |
| | 120 | |
| | 121 | {{{ |
| | 122 | sdac_drms=# \d public.sunum_queue; |
| | 123 | Table "public.sunum_queue" |
| | 124 | Column | Type | Modifiers |
| | 125 | --------------+-----------------------------+------------------------------------------------------- |
| | 126 | queue_id | bigint | not null default nextval('sunum_queue_key'::regclass) |
| | 127 | sunum | bigint | not null |
| | 128 | series_name | text | not null |
| | 129 | timestamp | timestamp without time zone | default now() |
| | 130 | recnum | bigint | |
| | 131 | request_type | character varying(10) | not null default 'MIRROR'::character varying |
| | 132 | priority | integer | not null default 0 |
| | 133 | Indexes: |
| | 134 | "sunum_queue_pkey" PRIMARY KEY, btree (queue_id) |
| | 135 | }}} |
| | 136 | |
| | 137 | The JMD will check this table for entries of files that it should retrieve. We use a trigger on the table under slony control to write records into the `sunum_queue` table. There is a script in the CVS tree to build the appropriate triggers: `vso/DataProviders/JSOC/db_triggers/sunum_queue_trigger_sampled.pl`. It takes the following arguments: |
| | 138 | {{{ |
| | 139 | Usage : ./sunum_queue_trigger_sampled.pl <series> [<instrument> [<cadence> [<max_age>]]] |
| | 140 | |
| | 141 | series : series name (with namespace) |
| | 142 | instrument : hmi or aia |
| | 143 | cadence : integer, in seconds (should be a multiple of 72 for aia, 45 for hmi) |
| | 144 | max_age : maximum age, in days, of records to queue (default 14 days) |
| | 145 | }}} |
| | 146 | |
| | 147 | If given with just a series name, it will emit the SQL commands to create a trigger that retrieves all updates for observations within the last 14 days. Specifying a cadence will allow you to retrieve observations at lower than the full data rate. Note that only SQL is emitted to STDOUT, so that you can redirect this cleanly to a file. Warnings and other messages are emitted to STDERR. |
| | 148 | |
| | 149 | {{{ |
| | 150 | [oneiros@sdo3 db_triggers]$ ./sunum_queue_trigger_sampled.pl hmi.v_720s |
| | 151 | |
| | 152 | -- You only need to issue this once. In theory, it'd have already been |
| | 153 | -- done as part of the setup for DRMS & slony: |
| | 154 | -- |
| | 155 | -- CREATE LANGUAGE plpgsql; |
| | 156 | |
| | 157 | CREATE OR REPLACE FUNCTION hmi_v_720s_fc() returns TRIGGER as $hmi_v_720s_trg$ |
| | 158 | BEGIN |
| | 159 | IF (TG_OP='INSERT' AND new.sunum > 0 and NEW.date__obs <> 'NaN') THEN |
| | 160 | IF ( EXTRACT('epoch' FROM NOW()) - NEW.date__obs < 222134367 ) THEN |
| | 161 | INSERT INTO sunum_queue (sunum,recnum,series_name) VALUES (new.sunum,NEW.recnum,'hmi.v_720s'); |
| | 162 | END IF; |
| | 163 | |
| | 164 | END IF; |
| | 165 | RETURN NEW; |
| | 166 | END |
| | 167 | $hmi_v_720s_trg$ LANGUAGE plpgsql; |
| | 168 | |
| | 169 | |
| | 170 | -- the drop trigger will fail the first time, but there's no 'OR REPLACE' on |
| | 171 | -- triggers, so this is so it'll work after the first time. |
| | 172 | -- (or just don't mess with the trigger; replacing the function is enough, |
| | 173 | -- as it's just linked by name) |
| | 174 | |
| | 175 | DROP TRIGGER hmi_v_720s_trg ON hmi.v_720s; |
| | 176 | CREATE TRIGGER hmi_v_720s_trg AFTER INSERT ON hmi.v_720s |
| | 177 | FOR EACH ROW EXECUTE PROCEDURE hmi_v_720s_fc(); |
| | 178 | }}} |
| | 179 | |
| | 180 | === VSO Shadow Tables === |
| | 181 | |
| | 182 | (note that most sites do not need this trigger. Only SDAC and NSO currently incur this extra overhead) |
| | 183 | |
| | 184 | To speed searching for data, the VSO generates a materialized view that we refer to as the 'shadow tables'. These tables are keep up-to-date with the DRMS series table via a trigger. There are two scripts to build the SQL commands necessary, both in CVS: |
| | 185 | `vso/DataProviders/JSOC/db_triggers/shadow_aia_template.pl` and `vso/DataProviders/JSOC/db_triggers/shadow_hmi_template.pl`. They take a series name as an argument. Note that only SQL is emitted to STDOUT, so that you can redirect this cleanly to a file. Warnings and other messages are emitted to STDERR. |
| | 186 | |
| | 187 | {{{ |
| | 188 | [oneiros@sdo3 db_triggers]$ perl shadow_hmi_template.pl hmi.v_720s |
| | 189 | SERIES : hmi.v_720s |
| | 190 | SHADOW : hmi__v_720s |
| | 191 | |
| | 192 | DROP TABLE vso.hmi__v_720s; |
| | 193 | |
| | 194 | CREATE TABLE vso.hmi__v_720s ( |
| | 195 | date_obs timestamp NOT NULL, |
| | 196 | date timestamp NOT NULL, |
| | 197 | t_rec_index bigint UNIQUE NOT NULL, |
| | 198 | recnum bigint UNIQUE NOT NULL, |
| | 199 | sunum bigint NOT NULL, |
| | 200 | slotnum integer NOT NULL, |
| | 201 | clusterid bigint NOT NULL, |
| | 202 | fileid varchar(255) UNIQUE NOT NULL, |
| | 203 | |
| | 204 | PRIMARY KEY (t_rec_index) |
| | 205 | ); |
| | 206 | |
| | 207 | CREATE INDEX vso_hmi__v_720s_cluster ON vso.hmi__v_720s ( clusterid ); |
| | 208 | CREATE INDEX vso_hmi__v_720s_date_obs ON vso.hmi__v_720s ( date_obs ); |
| | 209 | CREATE INDEX vso_hmi__v_720s_date ON vso.hmi__v_720s ( date ); |
| | 210 | |
| | 211 | GRANT SELECT ON vso.hmi__v_720s TO vso; |
| | 212 | |
| | 213 | |
| | 214 | CREATE OR REPLACE FUNCTION proc_update_vso_hmi__v_720s () |
| | 215 | RETURNS TRIGGER AS $proc_update_vso_hmi__v_720s$ |
| | 216 | DECLARE |
| | 217 | record_date_obs timestamp; |
| | 218 | record_date timestamp; |
| | 219 | record_rec_index bigint; |
| | 220 | record_recnum bigint; |
| | 221 | record_sunum bigint; |
| | 222 | record_slotnum integer; |
| | 223 | record_fileid varchar(255); |
| | 224 | record_clusterid bigint; |
| | 225 | deleted_record RECORD; |
| | 226 | BEGIN |
| | 227 | -- this seems out of order, I know. |
| | 228 | -- we look at the new record, and try to figure out if it's invalid |
| | 229 | -- if it is, we still need to try to clean up the old record. |
| | 230 | record_rec_index = NEW.t_rec_index; |
| | 231 | record_sunum = NEW.sunum; |
| | 232 | -- we dont do journaling -- but we *DO* want to figure out |
| | 233 | -- when SUs are replaced |
| | 234 | DELETE FROM vso.hmi__v_720s |
| | 235 | WHERE t_rec_index = record_rec_index |
| | 236 | RETURNING sunum |
| | 237 | INTO deleted_record; |
| | 238 | IF FOUND THEN |
| | 239 | IF deleted_record.sunum <> NEW.sunum THEN |
| | 240 | -- don't flag if it's still the same sunum (headers updated?) |
| | 241 | INSERT INTO public.sunum_replaced ( |
| | 242 | old_sunum, new_sunum |
| | 243 | ) VALUES ( |
| | 244 | deleted_record.sunum, NEW.sunum |
| | 245 | ); |
| | 246 | END IF; |
| | 247 | END IF; |
| | 248 | -- |
| | 249 | -- ocassionally, there's a missing record ... don't process those |
| | 250 | IF 'NaN' = NEW.date__obs THEN |
| | 251 | RETURN NEW; |
| | 252 | END IF; |
| | 253 | -- |
| | 254 | record_date_obs = dynamical_to_unix(NEW.date__obs); |
| | 255 | record_date = dynamical_to_unix(NEW.date); |
| | 256 | record_recnum = NEW.recnum; |
| | 257 | record_slotnum = NEW.slotnum; |
| | 258 | |
| | 259 | record_fileid = 'hmi__v_720s:'||record_rec_index||':'||record_rec_index; |
| | 260 | record_clusterid = ROUND( record_rec_index / 40 ); |
| | 261 | -- |
| | 262 | -- I couldve done this as INSERT INTO ... SELECT NEW.* |
| | 263 | -- but then theres that nasty concat and such. |
| | 264 | INSERT into vso.hmi__v_720s ( |
| | 265 | date_obs, date, t_rec_index, recnum, sunum, slotnum, clusterid, fileid |
| | 266 | ) values ( |
| | 267 | record_date_obs, record_date, record_rec_index, record_recnum, |
| | 268 | record_sunum, record_slotnum, record_clusterid, record_fileid |
| | 269 | ); |
| | 270 | -- |
| | 271 | RETURN NEW; |
| | 272 | -- |
| | 273 | EXCEPTION |
| | 274 | WHEN OTHERS THEN |
| | 275 | RAISE WARNING 'vso.hmi__v_720s : % : % : %', SQLSTATE, NEW.recnum, SQLERRM; |
| | 276 | RETURN NEW; |
| | 277 | END; |
| | 278 | $proc_update_vso_hmi__v_720s$ LANGUAGE 'plpgsql'; |
| | 279 | |
| | 280 | |
| | 281 | DROP TRIGGER trig_update_vso_hmi__v_720s ON hmi.v_720s; |
| | 282 | |
| | 283 | CREATE TRIGGER trig_update_vso_hmi__v_720s |
| | 284 | BEFORE INSERT OR UPDATE |
| | 285 | ON hmi.v_720s |
| | 286 | FOR EACH ROW |
| | 287 | EXECUTE PROCEDURE proc_update_vso_hmi__v_720s(); |
| | 288 | |
| | 289 | |
| | 290 | -- trigger it to run for the data already in the table |
| | 291 | UPDATE hmi.v_720s SET recnum=recnum; |
| | 292 | }}} |
| | 293 | |