+void zebra_admin_import_begin (ZebraHandle zh, const char *database)
+{
+ zebra_begin_trans (zh);
+ xfree (zh->admin_databaseName);
+ zh->admin_databaseName = xstrdup(database);
+}
+
+void zebra_admin_import_end (ZebraHandle zh)
+{
+ zebra_end_trans (zh);
+}
+
+void zebra_admin_import_segment (ZebraHandle zh, Z_Segment *segment)
+{
+ int sysno;
+ int i;
+ if (zh->service->active < 2)
+ return;
+ for (i = 0; i<segment->num_segmentRecords; i++)
+ {
+ Z_NamePlusRecord *npr = segment->segmentRecords[i];
+ const char *databaseName = npr->databaseName;
+
+ if (!databaseName)
+ databaseName = zh->admin_databaseName;
+ printf ("--------------%d--------------------\n", i);
+ if (npr->which == Z_NamePlusRecord_intermediateFragment)
+ {
+ Z_FragmentSyntax *fragment = npr->u.intermediateFragment;
+ if (fragment->which == Z_FragmentSyntax_notExternallyTagged)
+ {
+ Odr_oct *oct = fragment->u.notExternallyTagged;
+ printf ("%.*s", (oct->len > 100 ? 100 : oct->len) ,
+ oct->buf);
+
+ sysno = 0;
+ extract_rec_in_mem (zh, "grs.sgml",
+ oct->buf, oct->len,
+ databaseName,
+ 0 /* delete_flag */,
+ 0 /* test_mode */,
+ &sysno /* sysno */,
+ 1 /* store_keys */,
+ 1 /* store_data */,
+ 0 /* match criteria */);
+ }
+ }
+ }
+}
+
+void zebra_admin_create (ZebraHandle zh, const char *database)
+{
+ ZebraService zs;
+
+ zebra_begin_trans (zh);
+
+ zs = zh->service;
+ /* announce database */
+ if (zebraExplain_newDatabase (zh->service->zei, database, 0
+ /* explainDatabase */))
+ {
+ zh->errCode = 224;
+ zh->errString = "Database already exist";
+ }
+ zebra_end_trans (zh);
+}
+
+int zebra_string_norm (ZebraHandle zh, unsigned reg_id,
+ const char *input_str, int input_len,
+ char *output_str, int output_len)
+{
+ WRBUF wrbuf;
+ if (!zh->service->zebra_maps)
+ return -1;
+ wrbuf = zebra_replace(zh->service->zebra_maps, reg_id, "",
+ input_str, input_len);
+ if (!wrbuf)
+ return -2;
+ if (wrbuf_len(wrbuf) >= output_len)
+ return -3;
+ if (wrbuf_len(wrbuf))
+ memcpy (output_str, wrbuf_buf(wrbuf), wrbuf_len(wrbuf));
+ output_str[wrbuf_len(wrbuf)] = '\0';
+ return wrbuf_len(wrbuf);
+}
+
+
+void zebra_set_state (int val, int seqno)
+{
+ long p = getpid();
+ FILE *f = fopen ("state.LCK", "w");
+ fprintf (f, "%c %d %ld\n", val, seqno, p);
+ fclose (f);
+}
+
+void zebra_get_state (char *val, int *seqno)
+{
+ FILE *f = fopen ("state.LCK", "r");
+
+ *val = 'o';
+ *seqno = 0;
+
+ if (f)
+ {
+ fscanf (f, "%c %d", val, seqno);
+ fclose (f);
+ }
+}
+
+static int zebra_begin_read (ZebraHandle zh)
+{
+ int dirty = 0;
+ char val;
+ int seqno;
+
+
+ (zh->trans_no)++;
+
+ if (zh->trans_no != 1)
+ {
+ zebra_flush_reg (zh);
+ return 0;
+ }
+
+ zebra_get_state (&val, &seqno);
+ if (val == 'd')
+ val = 'o';
+ if (seqno != zh->seqno)
+ {
+ yaz_log (LOG_LOG, "reopen seqno cur/old %d/%d", seqno, zh->seqno);
+ dirty = 1;
+ }
+ else if (zh->last_val != val)
+ {
+ yaz_log (LOG_LOG, "reopen last cur/old %d/%d", val, zh->last_val);
+ dirty = 1;
+ }
+ if (!dirty)
+ return 0;
+
+ if (val == 'c')
+ zebra_lock_r (zh->lock_shadow);
+ else
+ zebra_lock_r (zh->lock_normal);
+
+ zh->last_val = val;
+ zh->seqno = seqno;
+
+ zebra_register_deactivate (zh);
+
+ zebra_register_activate (zh, 0, val == 'c' ? 1 : 0);
+ return 0;
+}
+
+static void zebra_end_read (ZebraHandle zh)
+{
+ (zh->trans_no)--;
+
+ if (zh->trans_no != 0)
+ return;
+
+ zebra_unlock (zh->lock_normal);
+ zebra_unlock (zh->lock_shadow);
+}
+
+void zebra_begin_trans (ZebraHandle zh)
+{
+ int pass;
+ int seqno = 0;
+ char val = '?';
+ const char *rval;
+
+ (zh->trans_no++);
+ if (zh->trans_no != 1)
+ {
+ return;
+ }
+
+ yaz_log (LOG_LOG, "zebra_begin_trans");
+#if HAVE_SYS_TIMES_H
+ times (&zh->tms1);
+#endif
+
+ /* lock */
+ rval = res_get (zh->service->res, "shadow");
+
+ for (pass = 0; pass < 2; pass++)
+ {
+ if (rval)
+ {
+ zebra_lock_r (zh->lock_normal);
+ zebra_lock_w (zh->lock_shadow);
+ }
+ else
+ {
+ zebra_lock_w (zh->lock_normal);
+ zebra_lock_w (zh->lock_shadow);
+ }
+
+ zebra_get_state (&val, &seqno);
+ if (val == 'c')
+ {
+ yaz_log (LOG_LOG, "previous transaction didn't finish commit");
+ zebra_unlock (zh->lock_shadow);
+ zebra_unlock (zh->lock_normal);
+ zebra_commit (zh);
+ continue;
+ }
+ else if (val == 'd')
+ {
+ if (rval)
+ {
+ BFiles bfs = bfs_create (res_get (zh->service->res, "shadow"));
+ yaz_log (LOG_LOG, "previous transaction didn't reach commit");
+ bf_commitClean (bfs, rval);
+ bfs_destroy (bfs);
+ }
+ else
+ {
+ yaz_log (LOG_WARN, "your previous transaction didn't finish");
+ }
+ }
+ break;
+ }
+ if (pass == 2)
+ {
+ yaz_log (LOG_FATAL, "zebra_begin_trans couldn't finish commit");
+ abort();
+ return;
+ }
+ zebra_set_state ('d', seqno);
+
+ zebra_register_activate (zh, 1, rval ? 1 : 0);
+ zh->seqno = seqno;
+}
+
+void zebra_end_trans (ZebraHandle zh)
+{
+ char val;
+ int seqno;
+ const char *rval;
+
+ zh->trans_no--;
+ if (zh->trans_no != 0)
+ return;
+
+ yaz_log (LOG_LOG, "zebra_end_trans");
+ rval = res_get (zh->service->res, "shadow");
+
+ zebra_flush_reg (zh);
+
+ zebra_register_deactivate (zh);
+
+ zebra_get_state (&val, &seqno);
+ if (val != 'd')
+ {
+ BFiles bfs = bfs_create (res_get (zh->service->res, "shadow"));
+ bf_commitClean (bfs, rval);
+ bfs_destroy (bfs);
+ }
+ if (!rval)
+ seqno++;
+ zebra_set_state ('o', seqno);
+
+ zebra_unlock (zh->lock_shadow);
+ zebra_unlock (zh->lock_normal);
+
+#if HAVE_SYS_TIMES_H
+ times (&zh->tms2);
+ logf (LOG_LOG, "user/system: %ld/%ld",
+ (long) (zh->tms2.tms_utime - zh->tms1.tms_utime),
+ (long) (zh->tms2.tms_stime - zh->tms1.tms_stime));
+
+#endif
+}
+
+void zebra_repository_update (ZebraHandle zh)
+{
+ zebra_begin_trans (zh);
+ logf (LOG_LOG, "updating %s", zh->rGroup.path);
+ repositoryUpdate (zh);
+ zebra_end_trans (zh);
+}
+
+void zebra_repository_delete (ZebraHandle zh)