Commit 2afe4a4f authored by yiwenshao's avatar yiwenshao

try to add lowmemory load

parent eae26fae
/*1. store data as column files, and restore data as plaintext insert query
* 2. plaintext insert query should be able to recover directly
* 3. should be able to used exsisting data to reduce the computation overhead(to be implemented)
*/
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>
#include "wrapper/reuse.hh"
#include "wrapper/common.hh"
#include "wrapper/insert_lib.hh"
using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::string;
using std::to_string;
static std::string embeddedDir="/t/cryt/shadow";
char * globalEsp=NULL;
int num_of_pipe = 4;
//global map, for each client, we have one WrapperState which contains ProxyState.
static std::map<std::string, WrapperState*> clients;
//This connection mimics the behaviour of MySQL-Proxy
Connect *globalConn;
/*for each field, convert the format to FieldMeta_Wrapper*/
static void init(){
std::string client="192.168.1.1:1234";
//one Wrapper per user.
clients[client] = new WrapperState();
//Connect phase
ConnectionInfo ci("localhost", "root", "letmein",3306);
const std::string master_key = "113341234";
char *buffer;
if((buffer = getcwd(NULL, 0)) == NULL){
perror("getcwd error");
}
embeddedDir = std::string(buffer)+"/shadow";
SharedProxyState *shared_ps =
new SharedProxyState(ci, embeddedDir , master_key,
determineSecurityRating());
assert(0 == mysql_thread_init());
//we init embedded database here.
clients[client]->ps = std::unique_ptr<ProxyState>(new ProxyState(*shared_ps));
clients[client]->ps->safeCreateEmbeddedTHD();
//Connect end!!
globalConn = new Connect(ci.server, ci.user, ci.passwd, ci.port);
}
//========================================================================================//
fullBackUp gfb;
struct batch{
vector<string> field_names;
vector<int> field_types;
vector<int> field_lengths;
};
batch ggbt;
/*should choose the right decryption onion*/
static
std::shared_ptr<ReturnMeta> getReturnMeta(std::vector<FieldMeta*> fms,
std::vector<FieldMetaTrans> &tfds){
assert(fms.size()==tfds.size());
std::shared_ptr<ReturnMeta> myReturnMeta = std::make_shared<ReturnMeta>();
int pos=0;
//construct OLK
for(auto i=0u;i<tfds.size();i++){
//the order is DET,OPE,ASHE,AGG. other onions are not decryptable!!
int index = getDecryptionOnionIndex(tfds[i]);
if(index==-1) assert(0);
onion o = tfds[i].getChoosenOnionO()[index];
SECLEVEL l = tfds[i].getOriginalFieldMeta()->getOnionMeta(o)->getSecLevel();
FieldMeta *k = tfds[i].getOriginalFieldMeta();
OLK curOLK(o,l,k);
bool use_salt = false;
if(needsSalt(curOLK))
use_salt = true;
addToReturn(myReturnMeta.get(),pos++,curOLK,use_salt,k->getFieldName());
if(use_salt)
addSaltToReturn(myReturnMeta.get(),pos++);
ggbt.field_types.push_back(tfds[i].getChoosenFieldTypes()[index]);
ggbt.field_names.push_back(tfds[i].getChoosenOnionName()[index]);
ggbt.field_lengths.push_back(tfds[i].getChoosenFieldLengths()[index]);
if(use_salt){
ggbt.field_types.push_back(tfds[i].getSaltType());
ggbt.field_names.push_back(tfds[i].getSaltName());
ggbt.field_lengths.push_back(tfds[i].getSaltLength());
}
}
return myReturnMeta;
}
/*init global full backup. */
static
void initGfb(std::vector<FieldMetaTrans> &res,std::string db,std::string table){
vector<string> field_names;
vector<int> field_types;
vector<int> field_lengths;
/*choosen onions should all be included in gfb. salt is also included
it's hard to decide whether a FieldMetaTrans has salt because the senmantic is different from that of FieldMeta.
*/
for(auto &item:res){
for(auto i:item.getChoosenOnionName()){
field_names.push_back(i);
}
for(auto i:item.getChoosenFieldTypes()){
field_types.push_back(i);
}
for(auto i:item.getChoosenFieldLengths()){
field_lengths.push_back(i);
}
if(item.getHasSalt()){
field_names.push_back(item.getSaltName());
field_types.push_back(item.getSaltType());
field_lengths.push_back(item.getSaltLength());
}
}
gfb.field_names = field_names;
gfb.field_types = field_types;
gfb.field_lengths = field_lengths;
//then we should read the vector
std::string prefix = std::string("data/")+db+"/"+table+"/";
for(unsigned int i=0u; i<gfb.field_names.size(); i++) {
std::string filename = prefix + gfb.field_names[i];
std::vector<std::string> column;
if(IS_NUM(gfb.field_types[i])){
load_num_file(filename,column);
}else{
load_string_file(filename,column,gfb.field_lengths[i]);
}
gfb.annoOnionNameToFileVector[gfb.field_names[i]] = std::move(column);
}
//init another map
for(unsigned int i=0;i<gfb.field_names.size();i++){
gfb.annoOnionNameToType[gfb.field_names[i]] = gfb.field_types[i];
}
}
/*load file, decrypt, and then return data plain fields in the type ResType*/
static ResType load_files(std::string db, std::string table){
std::unique_ptr<SchemaInfo> schema = myLoadSchemaInfo(embeddedDir);
//get all the fields in the tables.
std::vector<FieldMeta*> fms = getFieldMeta(*schema,db,table);
TableMetaTrans res_meta = loadTableMetaTrans(db,table);
std::vector<FieldMetaTrans> res = res_meta.getFts();
for(unsigned int i=0;i<fms.size();i++){
res[i].trans(fms[i]);
}
//then we should load all the fields available
initGfb(res,db,table);
std::shared_ptr<ReturnMeta> rm = getReturnMeta(fms,res);
vector<string> field_names = ggbt.field_names;
vector<int> field_types = ggbt.field_types;
vector<int> field_lengths = ggbt.field_lengths;
//why do we need this??
create_embedded_thd(0);
rawMySQLReturnValue resraw;
// vector<vector<string>> resss_field = loadTableFieldsForDecryption(db,
// table,field_names, field_types, field_lengths);
vector<vector<string>> res_field;
for(auto item:field_names){
res_field.push_back(gfb.annoOnionNameToFileVector[item]);
}
//then transform it to ress_fields
unsigned int length = res_field[0].size();
vector<vector<string>> ress_field;
for(unsigned int i=0u;i<length;i++){
vector<string> row;
for(unsigned int j=0u;j<res_field.size();j++){
row.push_back(res_field[j][i]);
}
ress_field.push_back(row);
}
resraw.rowValues = ress_field;
resraw.fieldNames = field_names;
for(unsigned int i=0;i<field_types.size();++i){
resraw.fieldTypes.push_back(static_cast<enum_field_types>(field_types[i]));
}
ResType rawtorestype = rawMySQLReturnValue_to_ResType(false, &resraw);
auto finalresults = decryptResults(rawtorestype,*rm);
return finalresults;
}
static
void local_wrapper(const Item &i, const FieldMeta &fm, Analysis &a,
List<Item> *const append_list){
//append_list->push_back(&(const_cast<Item&>(i)));
//do not use the plain strategy
std::vector<Item *> l;
const uint64_t salt = fm.getHasSalt() ? randomValue() : 0;
uint64_t IV = salt;
for (auto it : fm.orderedOnionMetas()) {
const onion o = it.first->getValue();
OnionMeta * const om = it.second;
std::string annoOnionName = om->getAnonOnionName();
if(gfb.annoOnionNameToFileVector.find(annoOnionName)!=gfb.annoOnionNameToFileVector.end()){
enum_field_types type = static_cast<enum_field_types>(gfb.annoOnionNameToType[annoOnionName]);
std::vector<std::string> &tempFileVector = gfb.annoOnionNameToFileVector[annoOnionName];
std::string in = tempFileVector.back();
if(IS_NUM(type)){
//std::string in("11");
unsigned int len = annoOnionName.size();
if(len>4u&&annoOnionName.substr(len-4)=="ASHE"){
l.push_back(MySQLFieldTypeToItem(type,in));
}else{
l.push_back( new (current_thd->mem_root)
Item_int(static_cast<ulonglong>(valFromStr(in))) );
}
}else{
//std::string in("hehe");
l.push_back(MySQLFieldTypeToItem(type,in));
}
tempFileVector.pop_back();
//l.push_back(&(const_cast<Item&>(i)));
}else{
l.push_back(my_encrypt_item_layers(i, o, *om, a, IV));
}
}
std::string saltName = fm.getSaltName();
if (fm.getHasSalt()) {
if(gfb.annoOnionNameToFileVector.find(saltName)!=gfb.annoOnionNameToFileVector.end()){
std::vector<std::string> &tempFileVector = gfb.annoOnionNameToFileVector[saltName];
std::string in = tempFileVector.back();
// enum_field_types type = static_cast<enum_field_types>(gfb.annoOnionNameToType[saltName]);
// l.push_back(MySQLFieldTypeToItem(type,in));
l.push_back( new (current_thd->mem_root)
Item_int(static_cast<ulonglong>(valFromStr(in)))
);
tempFileVector.pop_back();
}else{
l.push_back(new Item_int(static_cast<ulonglong>(salt)));
}
}
for (auto it : l) {
append_list->push_back(it);
}
}
int
main(int argc, char* argv[]){
init();
create_embedded_thd(0);
std::string db="tdb",table="student";
std::string ip="localhost";
if(argc==4){
ip = std::string(argv[1]);
db = std::string(argv[2]);
table = std::string(argv[3]);
}
std::unique_ptr<SchemaInfo> schema = myLoadSchemaInfo(embeddedDir);
schema.get();
const std::unique_ptr<AES_KEY> &TK = std::unique_ptr<AES_KEY>(getKey(std::string("113341234")));
Analysis analysis(db, *schema, TK, SECURITY_RATING::SENSITIVE);
/*choose decryption onion, load and decrypt to plain text*/
ResType res = load_files(db,table);
std::string annoTableName = analysis.getTableMeta(db,table).getAnonTableName();
const std::string head = std::string("INSERT INTO `")+db+"`.`"+annoTableName+"` ";
/*reencryption to get the encrypted insert!!!*/
for(auto &row:res.rows){
List<List_item> newList;
List<Item> *const newList0 = new List<Item>();
for(auto i=0u;i<res.names.size();i++){
std::string field_name = res.names[i];
FieldMeta & fm = analysis.getFieldMeta(db,table,field_name);
local_wrapper(*row[i],fm,analysis,newList0);
}
newList.push_back(newList0);
std::ostringstream o;
insertManyValues(o,newList);
std::cout<<(head+o.str())<<std::endl;
}
return 0;
}
......@@ -132,6 +132,8 @@ void initGfb(std::vector<FieldMetaTrans> &res,std::string db,std::string table){
gfb.field_lengths = field_lengths;
//then we should read the vector
std::string prefix = std::string("data/")+db+"/"+table+"/";
unsigned long tupleNum=0;
for(unsigned int i=0u; i<gfb.field_names.size(); i++) {
std::string filename = prefix + gfb.field_names[i];
std::vector<std::string> column;
......@@ -140,12 +142,17 @@ void initGfb(std::vector<FieldMetaTrans> &res,std::string db,std::string table){
}else{
load_string_file(filename,column,gfb.field_lengths[i]);
}
tupleNum = column.size();
gfb.annoOnionNameToFileVector[gfb.field_names[i]] = std::move(column);
}
//init another map
for(unsigned int i=0;i<gfb.field_names.size();i++){
gfb.annoOnionNameToType[gfb.field_names[i]] = gfb.field_types[i];
}
//extra transformation. transform rows to item*
for(unsigned int i=0;i<gfb.field_names.size();i++){
gfb.annoOnionNameToItemVector[gfb.field_names[i]] = itemNullVector(tupleNum);
}
}
/*load file, decrypt, and then return data plain fields in the type ResType*/
......@@ -192,7 +199,7 @@ static ResType load_files_low_memory(std::string db, std::string table){
for(unsigned int i=0;i<field_types.size();++i){
resraw.fieldTypes.push_back(static_cast<enum_field_types>(field_types[i]));
}
//mem 91%
ResType rawtorestype = rawMySQLReturnValue_to_ResType(false, &resraw);
auto finalresults = decryptResults(rawtorestype,*rm);
return std::move(finalresults);
......@@ -259,10 +266,12 @@ int
main(int argc, char* argv[]){
init();
create_embedded_thd(0);
std::string ip = "localhost";
std::string db="tdb",table="student";
if(argc==3){
db = std::string(argv[1]);
table = std::string(argv[2]);
ip = std::string(argv[1]);
db = std::string(argv[2]);
table = std::string(argv[3]);
}
std::unique_ptr<SchemaInfo> schema = myLoadSchemaInfo(embeddedDir);
......
......@@ -121,11 +121,10 @@ main(int argc, char* argv[]){
std::string db="tdb",table="student";
std::string ip="127.0.0.1";
int port=3306;
if(argc==5){
if(argc==4){
ip = std::string(argv[1]);
port = std::stoi(std::string(argv[2]));
db = std::string(argv[3]);
table = std::string(argv[4]);
db = std::string(argv[2]);
table = std::string(argv[3]);
}
init(ip,port);
store(db,table);
......
......@@ -4,18 +4,19 @@ using std::string;
int
main(int argc,char ** argv) {
if(argc<2){
std::cout<<"expect 1 or 2 arguments"<<std::endl;
if(argc!=3){
std::cout<<"expect ip and length"<<std::endl;
return 0;
}
string length(argv[1]);
string ip(argv[1]);
string length(argv[2]);
std::vector<string> create{
"create database micro_db;",
"use micro_db;",
string("create table str_table(name varchar(")+length+"));"
};
big_proxy b;
big_proxy b("tdb",ip,"root","letmein",3306);
for(auto item:create){
b.go(item);
}
......
#include "main/big_proxy.hh"
#include <vector>
using std::string;
int
main(int argc,char ** argv) {
std::vector<string> create{
"use micro_db;",
"insert into int_table values(1),(2),(3),(4),(5);",
};
if(argc!=2){
std::cout<<"1:ip"<<std::endl;
return 0;
}
std::string ip = std::string(argv[1]);
big_proxy b("tdb",ip,"root","letmein",3306);
for(auto item:create){
b.go(item);
}
return 0;
}
#include "main/big_proxy.hh"
#include <vector>
using std::string;
int
main(int argc,char ** argv) {
if(argc!=2){
std::cout<<"expect ip"<<std::endl;
return 0;
}
string ip(argv[1]);
std::vector<string> create{
"use micro_db;",
"insert into str_table values('a'),('b'),('c'),('d'),('e');"
};
big_proxy b("tdb",ip,"root","letmein",3306);
for(auto item:create){
b.go(item);
}
return 0;
}
#include "main/big_proxy.hh"
#include <vector>
using std::string;
int
main(int argc,char ** argv) {
std::vector<string> create{
"use micro_db;",
"select * from int_table;",
};
if(argc!=2){
std::cout<<"1:ip"<<std::endl;
return 0;
}
std::string ip = std::string(argv[1]);
big_proxy b("tdb",ip,"root","letmein",3306);
for(auto item:create){
b.go(item);
}
return 0;
}
#include "main/big_proxy.hh"
#include <vector>
using std::string;
int
main(int argc,char ** argv) {
if(argc!=2){
std::cout<<"expect ip and length"<<std::endl;
return 0;
}
string ip(argv[1]);
std::vector<string> create{
"use micro_db;",
"select * from str_table;"
};
big_proxy b("tdb",ip,"root","letmein",3306);
for(auto item:create){
b.go(item);
}
return 0;
}
......@@ -438,6 +438,16 @@ void load_num_file(std::string filename,std::vector<std::string> &res){
}
infile.close();
}
/*
void load_num_file(std::string filename,std::vector<Item> &res,enum_field_types intype){
std::ifstream infile(filename);
std::string line;
while(std::getline(infile,line)){
res.pusb_back((void*)MySQLFieldTypeToItem(intype,line));
}
infile.close();
}*/
void load_string_file(std::string filename, std::vector<std::string> &res,unsigned long length){
......@@ -450,6 +460,17 @@ void load_string_file(std::string filename, std::vector<std::string> &res,unsign
close(fd);
}
/*
void load_string_file(std::string filename,std::vector<void*> &res,unsigned long length,enum_field_types intype){
char *buf = new char[length];
int fd = open(filename.c_str(),O_RDONLY);
if(fd==-1) assert(0);//reading from -1 may cause errors
while(read(fd,buf,length)!=0){
res.push_back((void*)MySQLFieldTypeToItem(intype,std::string(buf,length)));
}
close(fd);
}
*/
std::ostream&
insertManyValues(std::ostream &out,List<List_item> &newList){
......
......@@ -167,6 +167,7 @@ struct fullBackUp{
std::vector<int> field_types;
std::vector<int> field_lengths;
std::map<std::string,std::vector<std::string>> annoOnionNameToFileVector;//field name to vector of string
std::map<std::string,std::vector<Item*>> annoOnionNameToItemVector;
std::map<std::string,int> annoOnionNameToType;
};
......@@ -184,3 +185,11 @@ getIntItem(int i);
std::unique_ptr<Item>
getStringItem(std::string s);
//Item* do not work
//void load_num_file(std::string filename,std::vector<Item> &res,enum_field_types intype);
//void load_string_file(std::string filename,std::vector<Item> &res,unsigned long length,enum_field_types intype);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment