📄 mal_box.mx
字号:
if (idcmp(box[j]->name, name) == 0) { free(box[i]->name); freeMalBlk(box[i]->sym); freeStack(box[i]->val); boxfile = boxFileName(box[i], 0); unlink(boxfile); GDKfree(boxfile); MT_destroy_lock(box[i]->lock); } else box[i] = box[j++]; } mal_unset_lock(mal_contextLock, "destroyBox");}@- OperationsThe deposit operation silently accepts any request to storean element.@cintdepositBox(Box box, str name, ValPtr val){ int i; ValPtr v; i = findVariable(box->sym, name); if (i < 0) { i = newVariable(box->sym, GDKstrdup(name), val->vtype); chkStack(box->val, i); } v = &box->val->stk[i]; box->val->stktop++; VALcopy(v, val); box->dirty= TRUE;#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "depositBox: entered '%s' at %d type %d\n", name, i, v->vtype);#endif return 0;}voidinsertToBox(Box box, str nme, str val){ ValRecord vr; vr.vtype = TYPE_str; vr.val.sval = val? val: (str)str_nil; vr.len = strlen(vr.val.sval); depositBox(box, nme, &vr);}@-Taking an element from a box is only permitted if the type ofthe receiver matches the type of the source.@cinttakeBox(Box box, str name, ValPtr val, int tpe){ int i; ValPtr v; i = findVariable(box->sym, name);#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "takeBox: found '%s' at %d\n", name, i);#endif if (i < 0) return i; v = &box->val->stk[i]; if (val->vtype != v->vtype && v->vtype != TYPE_any && tpe != TYPE_any) {#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "takeBox:type error %d,%d\n", val->vtype, box->val->stk[i].vtype);#endif return -1; } VALcopy(val, &box->val->stk[i]); if (val->vtype == TYPE_bat) BBPincref(val->val.br.id, TRUE);#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "takeBox:'%s' from '%s'\n", name, box->name);#endif return 0;}@-The function bindBAT relates a logical BAT name with a physicalrepresentation. The bind commands are typically found in the boxes,which provide users a partial view over the BAT storage area.That is, all bats bound can be taken out of the box upon need.A variable can be rebound to another BAT at any time.@cintbindBAT(Box box, str name, str location){ int i; ValPtr v; i = findVariable(box->sym, name); if (i < 0) i = newVariable(box->sym, GDKstrdup(name), TYPE_any); v = &box->val->stk[i]; v->val.br.id = BBPindex(location); if (v->val.br.id == 0) return -1; v->vtype = TYPE_bat;#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "bindBox:'%s' to '%s' [%d] in '%s'\n", name, location, v->val.br.id, box->name);#endif return 0;}intreleaseBox(Box box, str name){ int i;#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "releaseBox:%s from %s\n", name, box->name);#endif i = findVariable(box->sym, name); if (i < 0) return i; return 0;}intreleaseAllBox(Box box){#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "releaseAllBox:%s \n", box->name);#else (void) box;#endif return 0;}intdiscardBox(Box box, str name){ int i, j;#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "discardBox:%s from %s\n", name, box->name);#endif i = findVariable(box->sym, name); if (i < 0) return i; garbageElement(&box->val->stk[i]); for (j = i; j < box->sym->vtop - 2; j++) { box->sym->var[j] = box->sym->var[j + 1]; VALcopy(&box->val->stk[j], &box->val->stk[j + 1]); } box->sym->vtop--; box->val->stktop--; box->dirty= TRUE; return 0;}@-The elements can be obtained using iterator, which returns the nameof the next element in the box.@cintnextBoxElement(Box box, lng *cursor, ValPtr v){ if (*cursor >= box->sym->vtop) { *cursor = -1; return 0; } v->vtype = TYPE_str; v->val.pval = getBoxName(box, *cursor); *cursor = *cursor + 1; return 0;}strgetBoxName(Box box, lng i){ str s; s = getVarName(box->sym, (int) i); return GDKstrdup(s);}strtoString(Box box, lng i){ (void) box; (void) i; /* fool the compiler */ return GDKstrdup("");}strgetBoxNames(int *bid){ BAT *b; int i; b = BATnew(TYPE_int, TYPE_str, (size_t) MAXSPACES); for (i = 0; i < MAXSPACES; i++) if (box[i] != NULL) { BUNins(b, &i, box[i]->name, FALSE); } BBPincref(*bid = b->batCacheid, TRUE); BBPunfix(*bid); return MAL_SUCCEED;}@- PersistencyThe content of a box is saved on a file for subsequent re-use.The storage is explicitly in terms of MAL operations.For BAT objects, the corresponding object is made persistent.Note that the user can not control these operations directly.The box container is created if it did not yet exist.@cstrboxFileName(Box box, str backup){ char boxfile[PATHLENGTH]; size_t i = 0; snprintf(boxfile, PATHLENGTH, "%s%c%s%cbox", GDKgetenv("gdk_dbfarm"), DIR_SEP, GDKgetenv("gdk_dbname"), DIR_SEP); if (mkdir(boxfile, 0755) < 0 && errno != EEXIST) { showException(MAL,"box.fileName", "can not create box directory"); return NULL; } i = strlen(boxfile); if (backup) { snprintf(boxfile + i, PATHLENGTH - i, "%c%s", DIR_SEP, backup); if (mkdir(boxfile, 0755) < 0 && errno != EEXIST) { showException(MAL,"box.fileName", "can not create box directory"); return NULL; } i += strlen(backup) + 1; } snprintf(boxfile + i, PATHLENGTH - i, "%c%s.box", DIR_SEP, box->name); return GDKstrdup(boxfile);}#ifndef R_OK#define R_OK 4#endifstream *prepareSaveBox(Box box, str *boxfile, str *boxfilebak){ stream *f; *boxfile = boxFileName(box, 0); *boxfilebak = boxFileName(box, "backup"); if (*boxfile == 0) { showException(MAL, "box.saveBox", "can not determine box file"); return 0; } if (access(*boxfile,R_OK)==0 && rename(*boxfile, *boxfilebak)) {#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "saveBox:can not rename %s\n", boxfile);#endif showException(MAL,"box.saveBox", "can not rename backup"); GDKfree(*boxfile); *boxfile = NULL; GDKfree(*boxfilebak); *boxfilebak = NULL; return 0; } f = open_wastream(*boxfile);#ifndef S_IRUSR#define S_IRUSR 0400#define S_IWUSR 0200#endif if (f != NULL) chmod(*boxfile, (S_IRUSR | S_IWUSR)); else showException(MAL,"box.saveBox", "can not create box file"); if (f == NULL) { GDKfree(*boxfile); *boxfile= NULL; GDKfree(*boxfilebak); *boxfilebak= NULL; } return f;}intsaveBox(Box box, int flag){ int i; stream *f; ValPtr v; str boxfile, boxfilebak; (void) flag; /* fool the compiler */ if( box->dirty== FALSE) return 0; f = prepareSaveBox(box, &boxfile, &boxfilebak); if (f == NULL) return 1;#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "saveBox:created %s\n", boxfile);#endif for (i = 0; i < box->sym->vtop; i++) { v = &box->val->stk[i]; if (v->vtype == TYPE_bat) { BAT *b = (BAT *) BBPgetdesc(v->val.br.id); if (b && b->batPersistence & PERSISTENT){ stream_printf(f, "%s.bind(\"%s\",\"%s\");\n", box->name, getVarName(box->sym, i), BBPname(v->val.br.id)); BATcommit(b); } } else { stream_printf(f, "%s := ", getVarName(box->sym, i)); ATOMprint(v->vtype, VALptr(v), f); stream_printf(f, ":%s;\n", getTypeName(v->vtype)); stream_printf(f, "%s.deposit(\"%s\",%s);\n", box->name, getVarName(box->sym, i), getVarName(box->sym, i)); } } close_stream(f); GDKfree(boxfile); GDKfree(boxfilebak); return 0;}@-Loading a box is equivalent to reading a script.Beware to execute it into its own context.@cvoidloadBox(str name){ char boxfile[PATHLENGTH]; size_t i = 0; snprintf(boxfile, PATHLENGTH, "%s%c%s%cbox", GDKgetenv("gdk_dbfarm"), DIR_SEP, GDKgetenv("gdk_dbname"), DIR_SEP); mkdir(boxfile,0755); /* ignore errors */ i = strlen(boxfile); snprintf(boxfile + i, PATHLENGTH - i, "%c%s.box", DIR_SEP, name);#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "loadBox:start loading the file %s\n", boxfile);#endif if (access(boxfile, R_OK) == 0) { Client child= MCforkClient(MCgetClient()); defaultScenario(child); evalFile(child, boxfile, 0); MCkillClient(child,2);#ifdef DEBUG_MAL_BOX stream_printf(GDKout, "loadBox:loaded the file %s\n", boxfile);#endif }}@- UtilitiesUtilities for the debugger permit dumping of all the objectspaces.@cvoidprintBox(stream *fd, Box obj){ printStack(fd, obj->sym, obj->val,0);}voidprintSomeBox(stream *fd, int k){ if (box[k] == 0) { showException(MAL,"box.printSomeBox", "illegal space id: %d", k); } else printBox(fd, box[k]);}@}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -