github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/big_query/chart_struct_save_and_retrieve.go (about)

     1  package big_query
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/gob"
     6  	"fmt"
     7  	"net/http"
     8  
     9  	"github.com/pbberlin/tools/dsu"
    10  	"github.com/pbberlin/tools/net/http/loghttp"
    11  	"google.golang.org/appengine"
    12  )
    13  
    14  // Chart data
    15  //
    16  // Normally, datastore types are restricted.
    17  // For intstance a
    18  //    map[string]map[string]float64
    19  // can not be a datastore field.
    20  //
    21  // Therefore, this package takes a complex struct
    22  // and *globs* it into a byte array,
    23  // quasi normalizing it.
    24  //
    25  // It then saves the byte array within a dsu.WrapBlob
    26  //
    27  // This way, any struct can be saved into into datastore
    28  // using dsu.WrapBlob.
    29  type CData struct {
    30  	M          map[string]map[string]float64
    31  	VPeriods   []string
    32  	VLangs     []string
    33  	F_max      float64
    34  	unexported string
    35  }
    36  
    37  // http://stackoverflow.com/questions/12854125/go-how-do-i-dump-the-struct-into-the-byte-array-without-reflection
    38  
    39  func SaveChartDataToDatastore(w http.ResponseWriter, r *http.Request, cd CData, key string) string {
    40  
    41  	c := appengine.NewContext(r)
    42  
    43  	internalType := fmt.Sprintf("%T", cd)
    44  	//buffBytes, _	 := StringToVByte(s)  // instead of []byte(s)
    45  
    46  	// CData to []byte
    47  	serializedStruct := new(bytes.Buffer)
    48  	enc := gob.NewEncoder(serializedStruct)
    49  	err := enc.Encode(cd)
    50  	loghttp.E(w, r, err, false)
    51  
    52  	key_combi, err := dsu.BufPut(c,
    53  		dsu.WrapBlob{Name: key, VByte: serializedStruct.Bytes(), S: internalType}, key)
    54  	loghttp.E(w, r, err, false)
    55  
    56  	return key_combi
    57  }
    58  
    59  func GetChartDataFromDatastore(w http.ResponseWriter, r *http.Request, key string) *CData {
    60  
    61  	c := appengine.NewContext(r)
    62  
    63  	key_combi := "dsu.WrapBlob__" + key
    64  
    65  	dsObj, err := dsu.BufGet(c, key_combi)
    66  	loghttp.E(w, r, err, false)
    67  
    68  	serializedStruct := bytes.NewBuffer(dsObj.VByte)
    69  	dec := gob.NewDecoder(serializedStruct)
    70  	newCData := new(CData) // hell, it was set to nil above - causing this "unassignable value" error
    71  	err = dec.Decode(newCData)
    72  	loghttp.E(w, r, err, false, "VByte was ", dsObj.VByte[:10])
    73  
    74  	return newCData
    75  }
    76  
    77  func testGobDecodeEncode(w http.ResponseWriter, r *http.Request, m map[string]interface{}) {
    78  
    79  	c := appengine.NewContext(r)
    80  
    81  	nx := 24
    82  
    83  	// without custom implementation
    84  	// everything is encoded/decoded except field unexported
    85  	orig := CData{
    86  		M:          map[string]map[string]float64{"lang1": map[string]float64{"2012-09": 0.2}},
    87  		VPeriods:   []string{"2011-11", "2014-11"},
    88  		VLangs:     []string{"C", "++"},
    89  		F_max:      44.2,
    90  		unexported: "val of unexported",
    91  	}
    92  	fmt.Fprintf(w, "orig\n%#v\n", &orig)
    93  
    94  	// writing to []byte
    95  	serializedStruct := new(bytes.Buffer)
    96  	enc := gob.NewEncoder(serializedStruct)
    97  	err := enc.Encode(orig)
    98  	loghttp.E(w, r, err, false)
    99  
   100  	sx := serializedStruct.String()
   101  	lx := len(sx)
   102  	fmt.Fprintf(w, "byte data: \n%#v...%#v\n", sx[0:nx], sx[lx-nx:])
   103  
   104  	// saving to ds
   105  	key_combi, err := dsu.BufPut(c,
   106  		dsu.WrapBlob{Name: "chart_data_test_1", VByte: serializedStruct.Bytes(), S: "chart data"}, "chart_data_test_1")
   107  	loghttp.E(w, r, err, false)
   108  	// restoring from ds
   109  	dsObj, err := dsu.BufGet(c, key_combi)
   110  	loghttp.E(w, r, err, false)
   111  
   112  	p := r.FormValue("p")
   113  
   114  	// reading
   115  	rest1 := new(CData)
   116  	if p == "" {
   117  		sx := string(dsObj.VByte)
   118  		lx := len(sx)
   119  		fmt.Fprintf(w, "byte data: \n%#v...%#v\n", sx[0:nx], sx[lx-nx:])
   120  
   121  		readr := bytes.NewBuffer(dsObj.VByte)
   122  		dec := gob.NewDecoder(readr)
   123  		err = dec.Decode(rest1)
   124  		loghttp.E(w, r, err, false)
   125  	} else {
   126  		readr := bytes.NewBuffer(serializedStruct.Bytes())
   127  		dec := gob.NewDecoder(readr)
   128  		err = dec.Decode(rest1)
   129  		loghttp.E(w, r, err, false)
   130  	}
   131  
   132  	fmt.Fprintf(w, "resl\n%#v\n", rest1)
   133  
   134  	fmt.Fprintf(w, "\n\n")
   135  	SaveChartDataToDatastore(w, r, orig, "chart_data_test_2")
   136  
   137  	dsObj2, err := dsu.BufGet(c, "dsu.WrapBlob__chart_data_test_2")
   138  	loghttp.E(w, r, err, false)
   139  	{
   140  
   141  		rest2 := new(CData)
   142  
   143  		sx := string(dsObj2.VByte)
   144  		lx := len(sx)
   145  		fmt.Fprintf(w, "byte data: \n%#v...%#v\n", sx[0:nx], sx[lx-nx:])
   146  
   147  		readr := bytes.NewBuffer(dsObj2.VByte)
   148  		dec := gob.NewDecoder(readr)
   149  		err = dec.Decode(rest2)
   150  		loghttp.E(w, r, err, false)
   151  
   152  		fmt.Fprintf(w, "res2\n%#v\n", rest2)
   153  
   154  	}
   155  
   156  	f1 := GetChartDataFromDatastore(w, r, "chart_data_test_2")
   157  	fmt.Fprintf(w, "resl\n%#v\n", f1)
   158  
   159  }
   160  
   161  //  if we wanted to gob.Encode/Decode unexported fields,
   162  //  like CData.unexported, then we have to implement
   163  //  every field ourselves
   164  //  => uncomment following ...
   165  /*
   166  func (d *CData)GobEncode() ([]byte, error) {
   167  	w := new(bytes.Buffer)
   168  	encoder := gob.NewEncoder(w)
   169  	err := encoder.Encode(d.unexported)
   170  	if err!=nil { return nil, err }
   171  	return w.Bytes(), nil
   172  }
   173  
   174  func (d *CData)GobDecode(buf []byte) error {
   175  	r := bytes.NewBuffer(buf)
   176  	decoder := gob.NewDecoder(r)
   177  	return  decoder.Decode(&d.unexported)
   178  }
   179  */