/* fd is open connection to erlang node */ int ei_reg_dump(int fd, ei_reg *reg, const char *mntab, int flags) { ei_hash *tab; erlang_pid self; erlang_pid mnesia; ei_bucket *b; ei_reg_obj *obj; const char *key; ei_cnode *ec; int i; if (!reg || !mntab) return -1; /* return EI_BADARG; */ tab = reg->tab; /* make a self pid */ if ((ec = ei_fd_to_cnode(fd)) == NULL) { return -1; } strcpy(self.node,ei_thisnodename(ec)); self.num = fd; self.serial = 0; self.creation = ei_thiscreation(ec); if (mn_start_dump(fd,&self,&mnesia,mntab)) return -1; /* traverse the table, passing objects to mnesia */ for (i=0; i<tab->size; i++) { b=tab->tab[i]; while (b) { obj = (ei_reg_obj*)(b->value); /* cast to eliminate 'const' warning */ key = b->key; if ((flags & EI_FORCE) || (obj->attr & EI_DIRTY)) { if (obj->attr & EI_DELET) { if (mn_send_delete(fd,&mnesia,key)) { ei_send_exit(fd,&self,&mnesia,"delete failed"); return -1; } } else { if (mn_send_write(fd,&mnesia,key,obj)) { ei_send_exit(fd,&self,&mnesia,"update failed"); return -1; } } } b = b->next; } } /* end the transaction */ if (mn_send_commit(fd,&mnesia,&self)) { ei_send_exit(fd,&self,&mnesia,"commit failed"); return -1; } /* wait for unlink */ if (mn_get_unlink(fd)) return -1; /* this point only reached if all went ok so far... */ /* now remove all deleted objects, unless the caller asked us not to */ if (!(flags & EI_NOPURGE)) ei_reg_purge(reg); /* success */ return 0; }
int ei_reg_restore(int fd, ei_reg *reg, const char *mntab) { int i,j; char tag[32]; char sbuf[EISMALLBUF]; char *dbuf = NULL; char *msgbuf = NULL; char *keybuf = NULL; erlang_pid self; erlang_pid mnesia = {"",0,0,0}; erlang_msg msg; int index = 0; int len = 0; int msglen; int version = 0; int arity = 0; long count = 0; long maxkey = 0; long maxobj = 0; ei_cnode *ec; if (!reg || !mntab) return -1; /* return EI_BADARG; */ /* make a self pid */ if ((ec = ei_fd_to_cnode(fd)) == NULL) { return -1; } strcpy(self.node,ei_thisnodename(ec)); self.num = fd; self.serial = 0; self.creation = ei_thiscreation(ec); if (mn_start_restore(fd,&self,&mnesia,mntab,&count,&maxkey,&maxobj)) { /* send exit *only* if we have pid */ if (mnesia.node[0]) ei_send_exit(fd,&self,&mnesia,"bad response from rpc start"); return -1; } if (count <= 0) { ei_send_exit(fd,&self,&mnesia,"nothing to do"); return 0; } /* make sure receive buffer can handle largest expected message */ len = maxkey + maxobj + 512; if (len > EISMALLBUF) if (!(dbuf = malloc(len))) { ei_send_exit(fd,&self,&mnesia,"cannot allocate space for incoming data"); return -1; } msgbuf = (dbuf ? dbuf : sbuf); /* allocate space for largest key */ if (!(keybuf = malloc(maxkey+1))) goto restore_failure; /* get this ball rolling */ index = 0; ei_encode_version(msgbuf,&index); ei_encode_tuple_header(msgbuf,&index,2); ei_encode_atom(msgbuf,&index,"send_records"); ei_encode_pid(msgbuf,&index,&self); if (ei_send_encoded(fd,&mnesia,msgbuf,index)) goto restore_failure; /* read as much as possible, until count or EXIT */ for (i=0; i<count; i++) { index = len; while ((j = ei_recv_internal(fd,&msgbuf,&index,&msg,&msglen,1,0)) == 0) index = len; if (j<0) goto restore_failure; /* decode the first part of the message */ index = 0; if ((msg.msgtype != ERL_SEND) || ei_decode_version(msgbuf,&index,&version) || ei_decode_tuple_header(msgbuf,&index,&arity) || (arity != 6) || ei_decode_atom(msgbuf,&index,tag) || strcmp(tag,EI_MNESIA_RECV)) goto restore_failure; /* decode the rest of the message and insert data into table */ if (mn_decode_insert(reg,msgbuf,&index,keybuf)) goto restore_failure; } if (keybuf) free(keybuf); if (dbuf) free(dbuf); /* wait for unlink */ if (mn_unlink(fd)) return -1; /* clear all the dirty bits */ ei_hash_foreach(reg->tab,clean_obj); /* success */ return 0; restore_failure: ei_send_exit(fd,&self,&mnesia,"restore failure"); if (keybuf) free(keybuf); if (dbuf) free(dbuf); return -1; }
short erl_thiscreation(void) { return ei_thiscreation(&erl_if_ec); }