| 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 | |