/* * May be called with null parent, for root and ctl files. * The first call with a null parent is root, all others are ctl * files linked at root. */ Memblk* dfcreate(Memblk *parent, char *name, int uid, ulong mode) { Memblk *nf; Mfile *m; int isctl; if(fsfull()) error("file system full"); isctl = parent == nil; if(parent == nil) parent = fs->root; if(parent != nil){ dprint("dfcreate '%s' %M at\n%H\n", name, mode, parent); isdir(parent); isrwlocked(parent, Wr); ismelted(parent); }else dprint("dfcreate '%s' %M", name, mode); if(isctl) nf = dballoc(DBctl); else nf = dballoc(DBfile); if(catcherror()){ mbput(nf); if(parent != nil) rwunlock(parent, Wr); error(nil); } m = nf->mf; nf->d.id = nsec(); nf->d.mode = mode; nf->d.mtime = nf->d.id; nf->d.atime = nf->d.id; nf->d.length = 0; m->uid = usrname(uid); nf->d.uid = uid; m->gid = m->uid; nf->d.gid = nf->d.uid; m->muid = m->uid; nf->d.muid = nf->d.uid; m->name = name; nf->d.asize = pmeta(nf->d.embed, Embedsz, nf); changed(nf); if(parent != nil){ m->gid = parent->mf->gid; nf->d.gid = parent->d.gid; dflink(parent, nf); } noerror(); dprint("dfcreate-> %H\n within %H\n", nf, parent); return nf; }
int dblist_delitem(pgctx_t *ctx, dbtype_t list, int n, dbtype_t *item, int sync) { _list_t *_list, *_newlist = NULL; int sz, i, j; list.ptr = dbptr(ctx, list); assert(list.ptr->type == List); do { // Read-Copy-Update loop for modify operations _list = dbptr(ctx, list.ptr->list); if (!_list) return -1; // As in Python, negative list index means "from end of list" if (n<0) n += _list->len; if (n < 0 || n >= _list->len) return -1; sz = dblist_size(_list, 0); dbfree(_newlist, 0xf3); _newlist = dballoc(ctx, sz); _newlist->type = _InternalList; _newlist->len = _list->len - 1; for(i=j=0; i<_list->len; i++) { if (i==n) { *item = _list->item[i]; } else { _newlist->item[j++] = _list->item[i]; } } } while(!synchronizep(ctx, sync, &list.ptr->list, _list, _newlist)); dbfree(_list, 0xf4); return 0; }
int dblist_setitem(pgctx_t *ctx, dbtype_t list, int n, dbtype_t item, int sync) { _list_t *_list, *_newlist = NULL; int sz, llen; list.ptr = dbptr(ctx, list); assert(list.ptr->type == List); do { // Read-Copy-Update loop for modify operations _list = dbptr(ctx, list.ptr->list); llen = _list ? _list->len : 0; // As in Python, negative list index means "from end of list" if (n<0) n += llen; if (n < 0 || n >= llen) return -1; sz = dblist_size(_list, 0); dbfree(_newlist, 0xf1); _newlist = dballoc(ctx, sz); memcpy(_newlist, _list, sz); _newlist->item[n] = item; } while(!synchronizep(ctx, sync, &list.ptr->list, _list, _newlist)); dbfree(_list, 0xf2); return 0; }
int dblist_extend(pgctx_t *ctx, dbtype_t list, int n, extendcb_t elem, void *user, int sync) { _list_t *_list, *_newlist = NULL; int sz, i, j, llen; dbtype_t item; list.ptr = dbptr(ctx, list); assert(list.ptr->type == List); // Read-Copy-Update loop for modify operations do { _list = dbptr(ctx, list.ptr->list); llen = _list ? _list->len : 0; sz = dblist_size(_list, n); dbfree(_newlist, 0xf7); _newlist = dballoc(ctx, sz); _newlist->type = _InternalList; _newlist->len = llen + n; for(i=0; i<llen; i++) { _newlist->item[i] = _list->item[i]; } for(j=0; j<n; j++, i++) { if (elem(ctx, j, &item, user) < 0) { return -1; } _newlist->item[i] = item; } } while(!synchronizep(ctx, sync, &list.ptr->list, _list, _newlist)); dbfree(_list, 0xf8); return 0; }
int dblist_insert(pgctx_t *ctx, dbtype_t list, int n, dbtype_t item, int sync) { _list_t *_list, *_newlist = NULL; int sz, i, j, llen; list.ptr = dbptr(ctx, list); assert(list.ptr->type == List); // Read-Copy-Update loop for modify operations do { _list = dbptr(ctx, list.ptr->list); llen = _list ? _list->len : 0; // INT_MAX is a magic value that means append if (n == INT_MAX) n = llen; // As in Python, negative list index means "from end of list" if (n<0) n += llen; if (n < 0 || n > llen) return -1; sz = dblist_size(_list, 1); dbfree(_newlist, 0xf5); _newlist = dballoc(ctx, sz); _newlist->type = _InternalList; _newlist->len = llen + 1; for(i=j=0; i<_newlist->len; i++) { if (i == n) { _newlist->item[i] = item; } else { _newlist->item[i] = _list->item[j++]; } } } while(!synchronizep(ctx, sync, &list.ptr->list, _list, _newlist)); dbfree(_list, 0xf6); return 0; }
/* for dfblk only */ static Memblk* getmelted(uint isdir, uint type, daddrt *addrp, int *chg) { Memblk *b, *nb; *chg = 0; if(*addrp == 0){ b = dballoc(type); *addrp = b->addr; *chg = 1; return b; } b = dbget(type, *addrp); nb = nil; if(!b->frozen) return b; if(catcherror()){ mbput(b); mbput(nb); error(nil); } nb = dbdup(b); assert(type == b->type); if(isdir && type == DBdata) dupdentries(nb->d.data, Dblkdatasz/Daddrsz); USED(&nb); /* for error() */ *addrp = nb->addr; *chg = 1; dbput(b, b->type, b->addr); noerror(); mbput(b); return nb; }
dbtype_t dblist_new(pgctx_t *ctx) { dbtype_t list; list.ptr = dballoc(ctx, sizeof(dblist_t)); if (!list.ptr) return DBNULL; list.ptr->type = List; return dboffset(ctx, list.ptr); }
static dbtype_t bonsai_ncopy(pgctx_t *ctx, dbtype_t left, dbtype_t right, dbtype_t orig, int n) { dbtype_t node; unsigned copysz = 0; orig.ptr = dbptr(ctx, orig); if (orig.ptr->type == _BonsaiNode) { node.ptr = dballoc(ctx, sizeof(dbnode_t)); copysz = 2*sizeof(dbtype_t); } else if (orig.ptr->type == _BonsaiMultiNode) { node.ptr = dballoc(ctx, sizeof(dbmultinode_t) + orig.ptr->nvalue * sizeof(dbtype_t)); copysz = 2*sizeof(dbtype_t) + (orig.ptr->nvalue + n) * sizeof(dbtype_t); } node.ptr->type = orig.ptr->type; node.ptr->left = left; node.ptr->right = right; node.ptr->size = 1 + bonsai_size(ctx, left) + bonsai_size(ctx, right); memcpy(&node.ptr->key, &orig.ptr->key, copysz); rculoser(node, 0); return dboffset(ctx, node.ptr); }
static dbtype_t bonsai_new(pgctx_t *ctx, dbtype_t left, dbtype_t right, dbtype_t key, dbtype_t value) { dbtype_t node; node.ptr = dballoc(ctx, sizeof(dbnode_t)); node.ptr->type = _BonsaiNode; node.ptr->left = left; node.ptr->right = right; node.ptr->size = 1 + bonsai_size(ctx, left) + bonsai_size(ctx, right); node.ptr->key = key; node.ptr->value = value; rculoser(node, 0); return dboffset(ctx, node.ptr); }
int dblist_remove(pgctx_t *ctx, dbtype_t list, dbtype_t item, int sync) { _list_t *_list, *_newlist = NULL; int sz, i, j, remove; list.ptr = dbptr(ctx, list); assert(list.ptr->type == List); // Read-Copy-Update loop for modify operations do { _list = dbptr(ctx, list.ptr->list); if (!_list) return -1; sz = dblist_size(_list, 0); dbfree(_newlist, 0xf9); _newlist = dballoc(ctx, sz); _newlist->type = _InternalList; _newlist->len = _list->len - 1; remove = 0; for(i=j=0; i<_list->len; i++) { // Copy all items that don't match. Only remove // one matching item if (!remove && dbcmp(ctx, _list->item[i], item) == 0) { remove = 1; } else { _newlist->item[j++] = _list->item[i]; } } if (!remove) { dbfree(_newlist, 0xfa); // No item was removed, so discard the copy (no one will // ever see it) and return an error return -1; } } while(!synchronizep(ctx, sync, &list.ptr->list, _list, _newlist)); dbfree(_list, 0xfb); return 0; }