Db-GTM

 view release on metacpan or  search on metacpan

GTM.xs  view on Meta::CPAN

	      } 
	    }
	    setup->prefix = (strpack *)calloc(items+len-1,sizeof(strpack));
	    if(ix==3&&sv_isa(ST(0),"GtmEnvPtr")) for(i=sub->pfx_elem;i--;) {
	      strp = &sub->prefix[i]; gvnprefix = &setup->prefix[i];
	      gvnprefix->length = strp->length; gvnprefix->num = strp->num;
	      gvnprefix->address=(char *)calloc(strp->length+1,sizeof(char));
	      memcpy(gvnprefix->address, strp->address, strp->length);
	    }
	    for(i=1;i<items;i++) {
	      strp = &setup->prefix[i-1+len];
              test = (char *)SvPV(ST(i), strp->length);
              strp->address = (char *)calloc((strp->length)+1,sizeof(char));
	      memcpy(strp->address, test, strp->length);
	      strp->num = is_number(strp->address);
	      if(!strp->length) { warn("Init fail; null subscript.\n"); err++; }
              else tlen += strp->length;
	    }
            setup->pfx_elem = (items+len-1); setup->pfx_length = tlen; 
	    if(tlen > _GT_MAX_GVNLENGTH) { 
              warn("Init fail; prefix too long...\n"); err++; 
            }
	    if(err) { gtenv_clear(setup); }
          } 
          if(!err) { 
	    if(!_GTMinvoc) { // Save terminal settings to restore during END()
#ifdef _GT_NEED_TERMFIX
              _GTMterm = (struct termios *)calloc(1,sizeof(struct termios));
	      tcgetattr(STDIN_FILENO, _GTMterm);
#endif
#ifdef _GT_NEED_SIGFIX
	      sigint = signal(SIGINT, SIG_DFL); // Save SIGINT handler
#endif
	      setenv("GTMCI",_GT_GTMCI_LOC,0);
	      setenv("gtmroutines",_GT_GTMRTN_LOC,0);
	      setenv("gtmgbldir",_GT_GTMGBL_LOC,0);

              setup->last_err = gtm_init(); 
#ifdef _GT_NEED_SIGFIX
	      signal(SIGINT, sigint); // Restore SIGINT handler
#endif
            } else setup->last_err = 0;
            if(setup->last_err) { 
	      err_gtm(setup); gtenv_clear(setup); XSRETURN_UNDEF; 
	    } else { 
	      _GTMinvoc++; setup->gtmEnvId = _GTMinvoc; RETVAL = setup; 
            }
	  } else XSRETURN_UNDEF;
	}
	OUTPUT:
	RETVAL

void
gvn2list(...)
	ALIAS:
	  _str2list = 1
	  GTM::gvn2list  = 2
	  GTM::_str2list  = 3
	  GtmEnvPtr::gvn2list  = 4
	  GtmEnvPtr::_str2list  = 5
	PPCODE:
	{
          cppack *start = NULL, *next; SV *ret; unsigned s , x; char *glvn;
	  s = (ix < 4) ? 0 : 1; if(items < s) XSRETURN_UNDEF; 
	  start = unpackgvn( SvPV(ST(s),x) ); while(start) {
	    ret = sv_newmortal(); sv_setpv(ret, start->loc); XPUSHs(ret);
	    next = start->next; free(start); start = next;
          }
	}

void
list2gvn(...)
	ALIAS:
	  _list2str = 1
	  GTM::list2gvn = 2
	  GTM::_list2str = 3
	  GtmEnvPtr::list2gvn = 4
	  GtmEnvPtr::_list2str = 5
	  GtmEnvPtr::node = 6
	PPCODE:
	{
	  strpack *args; 
	  GtmEnv *pfx = (ix<4) ? NULL : (GtmEnv *)SvIV((SV*)SvRV(ST(0)));
	  unsigned i,s = (ix<4) ? 0 : 1, n; SV *ret;
	  gtm_string_t value, glvn;

	  EXTEND(SP,1); if(items>s) {
	    args = (strpack *)calloc(items-s,sizeof(strpack));
            for(i=s;i<items;i++) 
              args[i-s].address = (char *)SvPV(ST(i),args[i-s].length);
	    n=packgvn(pfx,items-s,args,(ix<4)?NO_PREFIX:0,&glvn); free(args); 
	  } else { n = packgvn(pfx,0,NULL,0,&glvn); }
	  if(glvn.address) { 
	    ret = sv_newmortal(); sv_setpv(ret, glvn.address); PUSHs(ret);
	    if(n) free(glvn.address);
	  } else PUSHs(&PL_sv_undef); 
	}

void
END()
	PPCODE:
	{
	   if( _GTMinvoc ) {
	     gtm_exit();
#ifdef _GT_NEED_TERMFIX
	     tcsetattr(STDIN_FILENO,0,_GTMterm); free(_GTMterm); 
#endif
	     _GTMinvoc = 0;
           }
	}

MODULE = Db::GTM		PACKAGE = GtmEnvPtr

void
DESTROY(gt_env)
	GtmEnv *gt_env
	PPCODE:
	{
	   gtenv_clear(gt_env);
	}

void
get(gt_env,...)
	GtmEnv *gt_env
	ALIAS:
	  retrieve = 1
	  FETCH = 2
	  EXISTS = 3
	  exists = 4
	PPCODE:
	{
	  strpack *args; unsigned i; 
	  unsigned long exst=0,n; gtm_string_t value,glvn; 
	  SV *ret=sv_newmortal(); EXTEND(SP, 1);

          if( GIMME_V==G_VOID ) XSRETURN_UNDEF; if(items>1) { 
            args = (strpack *)calloc(items-1,sizeof(strpack));
	    for(i=1;i<items;i++) 
              args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
	    n=packgvn(gt_env,items-1,args,(gt_env->flags & TIED),&glvn);
            free(args); 
	  } else { n=packgvn(gt_env,0,NULL,0,&glvn); }
	  if(glvn.address) {
	    value.address = gt_env->xfer_buf;
	    gt_env->last_err=gtm_ci("get",&value,&glvn,&exst);
            if(n) free(glvn.address); 
	
            if(gt_env->last_err) { err_gtm(gt_env); PUSHs(&PL_sv_undef); }
            else if(ix == 3 || ix == 4) PUSHs(newSViv(exst ? 1 : 0));
            else if(ix == 5)            PUSHs(newSViv(exst > 1 ? 1 : 0));
            else if(exst == 0 || exst == 10) PUSHs(&PL_sv_undef); 
	    else { sv_setpvn(ret, value.address, value.length); PUSHs(ret); } 
          }   else PUSHs(&PL_sv_undef); // Bad GVN name
	}

void
set(gt_env,...)
	GtmEnv *gt_env
	ALIAS:
	  store = 1
	  STORE = 2
	PPCODE:
	{
	  strpack *args; unsigned i,n; gtm_string_t glvn;

	  if(items>2) {
	    args = (strpack *)calloc(items-2,sizeof(strpack));
	    for(i=1;i<(items-1);i++) 
              args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
	    n=packgvn(gt_env,items-2,args,(gt_env->flags & TIED),&glvn);
            free(args); 
	  } else { n=packgvn(gt_env,0,NULL,0,&glvn); }
	  EXTEND(SP,1); if(glvn.address) {
            if(inTxn(gt_env)) {
	      gt_env->last_err = gtm_ci("txset", &glvn,
                                        (char *)SvPV(ST(items-1),i),
					gt_env->gtmEnvId
                                       );
            } else {
	      gt_env->last_err=gtm_ci("set",&glvn,(char *)SvPV(ST(items-1),i));
            }
	    if(n) free(glvn.address); if(gt_env->last_err) {
	      err_gtm(gt_env); 
	      XPUSHs(newSViv(gt_env->last_err)); // GTM error
	    } else XPUSHs(newSViv(0)); // Set OK
          }   else XPUSHs(newSViv(1)); // Bad GVN name
	}

void
order(gt_env,...)
	GtmEnv *gt_env
	ALIAS:
	  next = 1
	  NEXTKEY = 2
	  first = 3
	  FIRSTKEY = 4
	  haschildren = 5
	  last = 6
	  revorder = 7
	  prev = 8
	PPCODE:
	{
	  strpack *args,*x; unsigned i, aq=0,n; int dir=(ix>5)?-1:1; SV *ret;
	  char *addquot=""; gtm_string_t value, glvn;

          if( GIMME_V==G_VOID ) XSRETURN_UNDEF;
	  if(items==1 || (ix>2 && ix<7) ) { items++; aq++; }
	  args = (strpack *)calloc(items-1,sizeof(strpack));
          for(i=1;i<(items-aq);i++) 
            args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
	  if(aq) { args[items-2].address = addquot; args[items-2].length  = 0; }
	  n=packgvn(gt_env,items-1,args,ZEROLEN_OK|(gt_env->flags&TIED),&glvn);
          free(args); EXTEND(SP,1); if(glvn.address) {
	    value.address = gt_env->xfer_buf;
	    gt_env->last_err = gtm_ci("order",&value,&glvn,dir);
	    if(gt_env->last_err) { err_gtm(gt_env); PUSHs(&PL_sv_undef); } 
            else if(!value.length && GIMME_V==G_ARRAY) ; // Nothing to do
            else if(!value.length) PUSHs(&PL_sv_undef); 
	    else if(ix == 5) PUSHs(newSViv(1)); 
            else {
              if( GIMME_V==G_ARRAY ) {
                EXTEND(SP,items-1); for(i=1;i<(items-1);i++) PUSHs(ST(i));
              }
              PUSHs(newSVpvn(value.address, value.length));
            }
	    if(n) free(glvn.address); 
          } else PUSHs(&PL_sv_undef); // Bad GVN name
	}

void
kill(gt_env,...)
	GtmEnv *gt_env
	ALIAS:
	  DELETE = 1
	  CLEAR = 2
	  ks = 3
	  kv = 4
	PPCODE:
	{
	  strpack *args; unsigned i,n; gtm_string_t glvn;

          if(items>1) {
	    args = (strpack *)calloc(items-1,sizeof(strpack));
            for(i=1;i<items;i++) 
              args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
	    n = packgvn(gt_env,items-1,args,(gt_env->flags & TIED),&glvn); 
            free(args); 
	  } else { n = packgvn(gt_env,0,NULL,0,&glvn); }
	  EXTEND(SP,1); if(glvn.address) {
            if(inTxn(gt_env)) {
              i = (gtm_long_t)gt_env->gtmEnvId;
	      switch(ix) {
	        case 0: case 1: case 2:
                        gt_env->last_err = gtm_ci("txkill",&glvn,i); break;
	        case 3: gt_env->last_err = gtm_ci("txks",&glvn,i);   break;
	        case 4: gt_env->last_err = gtm_ci("txkv",&glvn,i);   break;
	        default: break;
	      }
            } else {
	      switch(ix) {
	        case 0: case 1: case 2:
                        gt_env->last_err = gtm_ci("kill",&glvn); break;
	        case 3: gt_env->last_err = gtm_ci("ks",&glvn);   break;
	        case 4: gt_env->last_err = gtm_ci("kv",&glvn);   break;
	        default: break;
	      }
            }
	    if(n) free(glvn.address); if(gt_env->last_err) {
	      err_gtm(gt_env); PUSHs(newSViv(gt_env->last_err));
	    } else PUSHs(newSViv(0)); // Kill OK
          }   else PUSHs(newSViv(1)); // Bad GVN name
	}

void
query(gt_env,...)
	GtmEnv *gt_env
	PPCODE:
	{
	  SV *ret; char **brk; 
	  strpack *args; cppack *start=NULL,*next; gtm_string_t value, glvn;
	  unsigned i,z,n; 

          if( GIMME_V==G_VOID ) XSRETURN_UNDEF; if(items>1) {
	    args = (strpack *)calloc(items-1,sizeof(strpack));
	    for(i=1;i<items;i++) 
              args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
	    n=packgvn(gt_env,items-1,args,0,&glvn); free(args); 
	  } else { n = packgvn(gt_env,0,NULL,0,&glvn); }
	  if(glvn.address) {
	    value.address = gt_env->xfer_buf;
	    gt_env->last_err = gtm_ci("query",&value,&glvn);
	    if(n) free(glvn.address); if(gt_env->last_err) {
              err_gtm(gt_env); XPUSHs(&PL_sv_undef);
	    } else {
	      value.address[value.length] = '\0'; 
	      start = unpackgvn(value.address); z=0; 
	        for(i=(gt_env->pfx_elem);i--;) {
		if(!start && 
	            strncmp(start->loc,
                            gt_env->prefix[i].address,
                            gt_env->prefix[i].length) 
                  ) z++;
		if(start) { next = start->next; free(start); start = next; }	
	      }
	      if(z) { // We're not in kansas anymore
		while(start) { next = start->next; free(start); start = next; }
	      } else while(start) {
	        ret = sv_newmortal(); sv_setpv(ret, start->loc); XPUSHs(ret);
		next = start->next; free(start); start = next;
              }
	    }
          } else XPUSHs(&PL_sv_undef);
	}

void
children(gt_env,...)
	GtmEnv *gt_env
	PPCODE:
	{
          char *end="\")\x00\x00",*loc; unsigned count=0,n,kids=0,base;
	  strpack *args; gtm_string_t value,glvn,buf; 

          if( GIMME_V==G_VOID ) XSRETURN_UNDEF;
	  buf.address = (char *)calloc(_GT_MAX_GVNLENGTH+5,sizeof(char));
	  if(items>1) {
	    unsigned i; items--;
            args = (strpack *)calloc(items,sizeof(strpack));
	    for(i=0;i<items;i++) 
              args[i].address = (char *)SvPV(ST(i+1),args[i].length);
	    n=packgvn(gt_env,items,args,0,&glvn); free(args); 
	  } else { n = packgvn(gt_env,0,NULL,0,&glvn); }
	  if(glvn.address) {
            count=glvn.length-1; 
            memcpy(buf.address,glvn.address,count); loc=buf.address+count-1; 
            if( buf.address[count-1] == ')' ) { *loc = ','; loc++; }
	    else { loc++; *loc = '('; loc++; }
            sprintf(loc,"\"\")"); loc++; value.address = loc;
	    base=(unsigned)(loc - buf.address); buf.length = base+2;
	   
	    gt_env->last_err = gtm_ci("order",&value,&buf,1); 
            unsigned wantarray=(GIMME_V==G_ARRAY); 
	    while(!gt_env->last_err && value.length) {
              if(wantarray) XPUSHs(newSVpvn(value.address, value.length));
	      kids++; memcpy(value.address+value.length, end, 4);
	      buf.length = base + value.length + 2;
	      gt_env->last_err = gtm_ci("order",&value,&buf,1); 
            }
	    if(gt_env->last_err) err_gtm(gt_env); if(n) free(glvn.address);
          }
	  free(buf.address); if(GIMME_V == G_SCALAR) XPUSHs(newSViv(kids));
	}

void
copy(...)
	ALIAS:
	  GTM::copy  = 4
	  GTMDB::copy  = 8
	  merge = 1
	  GTM::merge  = 5
	  GTMDB::merge  = 9
	  clobber = 2
	  GTM::clobber = 6
	  GTMDB::clobber = 10
	  overwrite = 3
	  GTM::overwrite = 7
	  GTMDB::overwrite = 11
	PPCODE:
	{
	  strpack *args; unsigned i,mid=0,ov=(ix & 2)?1:0,ob=(ix<4)?1:0,s=1,d=1;
	  GtmEnv *gt_env = (ob) ? (GtmEnv *)SvIV((SV*)SvRV(ST(0))) : NULL;
	  gtm_string_t src, dst; unsigned fs, fd; strpack value; SV *ret;

	  EXTEND(SP,1); if(items == (ob+2)) { 
	    // Two arguments passed in...
	    // They could either be GtmEnvPtrs (PERL GTMDB objects)
	    //   or they could be global names like ^FOO("BAR"), or both
	    if(!sv_isa(ST(ob),"GtmEnvPtr")) { 
              fs=0; src.address=(char *)SvPV(ST(ob),src.length);
            } else fs=packgvn((GtmEnv *)SvIV((SV*)SvRV(ST(ob))),0,NULL,0,&src);
	    if(!sv_isa(ST(ob+1),"GtmEnvPtr")) { 
              fd=0; dst.address=(char *)SvPV(ST(ob+1),dst.length);
            }else fd=packgvn((GtmEnv *)SvIV((SV*)SvRV(ST(ob+1))),0,NULL,0,&dst);

	  } else if(ob && items == 2 && sv_isa(ST(1),"GtmEnvPtr") ) {
            fs = packgvn((GtmEnv *)SvIV((SV*)SvRV(ST(1))),0,NULL,0,&src);
	    fd = packgvn(gt_env,0,NULL,0,&dst); 
	  } else if(items>ob) {
	    args = (strpack *)calloc(items-ob,sizeof(strpack)); fs = 1; fd = 1;
	    for(i=ob;i<items;i++) {
              args[i-ob].address = (char *)SvPV(ST(i),args[i-ob].length);
	      if(!args[i-ob].length && !mid) mid = i-ob;
	    }
	    if(!mid && ob) { // No target specified, assume it's us
	      packgvn(gt_env,items-1,args,0,&src); 
	      packgvn(gt_env,0,NULL,0,&dst); 
	    } else {
	      packgvn(gt_env,mid,args,0,&src); 
	      packgvn(gt_env,(items-(mid+1+ob)),&args[mid+1],0,&dst);
            }
            free(args); 
	  }
	  if(src.address && dst.address) {
            if(inTxn(gt_env)) {
              i = gt_env->gtmEnvId;
	      if(!ov) gt_env->last_err = gtm_ci("txcopy",&src,&dst,i); 
	      else    gt_env->last_err = gtm_ci("txclone",&src,&dst,i); 
            } else {
	      if(!ov) gt_env->last_err = gtm_ci("copy",&src,&dst); 
	      else    gt_env->last_err = gtm_ci("clone",&src,&dst); 
            }
	    if(gt_env->last_err) { 
	      err_gtm(gt_env); PUSHs(newSViv(gt_env->last_err)); 
            } else PUSHs(newSViv(0));
	  } else PUSHs(newSViv(1)); // Bad GVN name(s)
	  if(fs && src.address) free(src.address); 
          if(fd && dst.address) free(dst.address); 
	}

void
txnstart(gt_env)
	GtmEnv *gt_env
	ALIAS:
	  txnabort = 1
	  txncommit = 2
	PPCODE:
	{
	  EXTEND(SP,1); switch(ix) {
            case 0: gt_env->flags |= IN_TXN; break;
            case 1: if(inTxn(gt_env)) {
		      gt_env->last_err = gtm_ci("tabort",gt_env->gtmEnvId); 
		      gt_env->flags -= IN_TXN;
		    }
                    break;
            case 2: if(inTxn(gt_env)) {
		      gt_env->last_err = gtm_ci("tcommit",gt_env->gtmEnvId); 
		      if(!gt_env->last_err) gt_env->flags -= IN_TXN;
                    }
		    break;
	  }
	  if(gt_env->last_err) {
            err_gtm(gt_env); PUSHs(newSViv(gt_env->last_err)); // GTM error
          } else PUSHs(newSViv(0)); // Txn command OK
	}

void
lock(gt_env,...)
	GtmEnv *gt_env
	PPCODE:
	{
          strpack *args; unsigned i,n; gtm_string_t glvn;
	  gtm_long_t value, timeout = 0;

          if(items>1) {
            timeout = (gtm_long_t)SvIV(ST(items-1));
            args = (strpack *)calloc(items-2,sizeof(strpack));
            for(i=1;i<(items-1);i++)
              args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
            n=packgvn(gt_env,items-2,args,(gt_env->flags & TIED),&glvn);
            free(args);
          } else { n=packgvn(gt_env,0,NULL,0,&glvn); }

	  if(glvn.address) {
	    EXTEND(SP,1); 
            gt_env->last_err=gtm_ci("lock",&value,&glvn,timeout);
            if(n) free(glvn.address); 

	    if(!value) { 
              gt_env->last_err=1; PUSHs(newSViv(1));
              sprintf(gt_env->errmsg,"ERROR: Lock not obtained.");
            } else if(gt_env->last_err) {
              err_gtm(gt_env); PUSHs(newSViv(gt_env->last_err)); // GTM error
            } else PUSHs(newSViv(0)); // Lock OK
	  }
	}

void
unlock(gt_env,...)
	GtmEnv *gt_env
	PPCODE:
	{
          strpack *args; unsigned i,n; gtm_string_t glvn;

          if(items>1) {
            args = (strpack *)calloc(items-1,sizeof(strpack));
            for(i=1;i<items;i++)
              args[i-1].address = (char *)SvPV(ST(i),args[i-1].length);
            n=packgvn(gt_env,items-1,args,(gt_env->flags & TIED),&glvn);
            free(args);
          } else { n=packgvn(gt_env,0,NULL,0,&glvn); }

	  if(glvn.address) {
	    EXTEND(SP,1); gt_env->last_err=gtm_ci("unlock",&glvn);
            if(n) free(glvn.address); if(gt_env->last_err) {
              err_gtm(gt_env); PUSHs(newSViv(gt_env->last_err)); // GTM error
            } else PUSHs(newSViv(0));  // Unlock OK
	  }
	}

void
getid(gt_env)
	GtmEnv *gt_env
	PPCODE:
	{
	  XPUSHs(newSViv(gt_env->gtmEnvId));
	}

void
getprefix(gt_env)
	GtmEnv *gt_env
	PPCODE:
	{
          strpack *x; unsigned i; EXTEND(SP,gt_env->pfx_elem);
	  if(gt_env->prefix) for(i=0;i<(gt_env->pfx_elem);i++) {
	    x=&gt_env->prefix[i]; PUSHs(newSVpvn(x->address, x->length));
          }
	}



( run in 2.885 seconds using v1.01-cache-2.11-cpan-71847e10f99 )