ObjStore

 view release on metacpan or  search on metacpan

API/osperl.c  view on Meta::CPAN

{ conflict = thru; }

void osp_pathexam::no_conflict()
{
  assert(target);
  if (conflict) {
    croak("Attempt to add %s(0x%p) '%s' to multiple indices using the same indexing key '%s'",
	  target->os_class(&PL_na), target, kv_string(), conflict);
  }
}

// NOTE: An index conflict is only a problem if we are actually going
// to add the record to the index.  If the record is already added,
// setting lots of index flags isn't going to matter because they
// are already set.  OTOH, if the record fails the pathexam half
// way through we should back-out all the index flags that were
// set.  This doesn't happen yet, so the flags could become set
// unnecessarily and permenantly.  This could be construed as a bug
// but getting the right behavior is a hassel.  It's almost not
// worth it.  Perhaps the current behavior should be documented? XXX

// THE WORK-AROUND IS TO GET THE KEYS TWICE; THE FIRST TIME JUST
// TO SEE IF IT WORKS; THE SECOND TIME TO SET THE INDEX FLAGS.  YUCK.

int osp_pathexam::load_target(char _mode, OSSVPV *pv)
{
  if (!pathcnt) croak("no path loaded");
  keycnt = 0;
  conflict = 0;
  tmpkey = 0;
  target = pv;
  if (pv->is_OSPV_Ref2())
    pv = ((OSPV_Ref2*)pv)->focus();

  for (int xa=0; xa < pathcnt; xa++) {
    OSSV *kv = path_2key(xa, pv, _mode);
    if (!kv || !kv->is_set()) return 0; //need to undo flag changes; yuck XXX
    keys[xa] = kv;
    ++keycnt;
  }
  return 1;
}

OSSV *osp_pathexam::mod_ossv(OSSV *sv)
{
  if (sv && !OSvREADONLY(sv) && sv->is_set()) {
    if (get_mode() == 's') {
      if (OSvINDEXED(sv)) {
	set_conflict();
	DEBUG_pathexam(warn("conflict %s", get_thru()));
      }
      else OSvINDEXED_on(sv);
    } else if (get_mode() == 'u') {
      OSvINDEXED_off(sv);
    }
  }
  return sv;
}

// This API is a bit strange because we need to read off
// the perl stack (which can be relocated).  See XSUB.h.
void osp_pathexam::load_args(int ax, int items)
{
  int args = items - 1;
  if (args > OSP_PATHEXAM_MAXKEYS) {
    warn("Too many keys (%d) in load_args -- truncated to %d keys",
	 args, OSP_PATHEXAM_MAXKEYS);
    args = OSP_PATHEXAM_MAXKEYS;
  }
  keycnt = 0;
  conflict = 0;
  for (int xa=0; xa < args; xa++) {
    tmpkeys[xa] = ST(1+xa);
    keys[xa] = &tmpkeys[xa];
    ++keycnt;
  }
}

char *osp_pathexam::kv_string()
{
  char buf[64]; //XXX danger!
  SV *kv = newSVpvn("",0);
  SAVEFREESV(kv);
  int maxcnt = pathcnt > keycnt? pathcnt : keycnt;
  for (int p1=0; p1 < maxcnt; p1++) {
    if (p1 < pathcnt) {
      OSSVPV *path = pcache[p1];
      int plen = path->FETCHSIZE();
      for (int p2=0; p2 < plen; p2++) {
	sv_catpv(kv, path->avx(p2)->stringify(buf));
	if (p2 < plen-1) sv_catpv(kv, "/");
      }
    }
    if (p1 < keycnt) {
      if (p1 < pathcnt) sv_catpv(kv,"=");
      sv_catpv(kv, keys[p1]->stringify(buf));
    }
    if (p1 < maxcnt-1) sv_catpv(kv, ", ");
  }
  return SvPV(kv, PL_na);
}

void osp_pathexam::push_keys()
{
  SV *sv[OSP_PATHEXAM_MAXKEYS];
  for (int kx=0; kx < keycnt; kx++) {
    sv[kx] = osp_thr::ossv_2sv(get_key(kx));
  }
  dSP;
  EXTEND(SP, get_keycnt());
  for (kx=0; kx < get_keycnt(); kx++)
    PUSHs(sv[kx]);
  PUTBACK;
}

int osp_pathexam::compare(osp_keypack1 &kpk, int partial)
{
  if (!pathcnt) croak("no path loaded");
  int cmp;
  for (int kx=0; kx < pathcnt; kx++) {
    if (kx >= keycnt) {



( run in 1.743 second using v1.01-cache-2.11-cpan-71847e10f99 )