Beispiel #1
0
// Trip performs a roundtrip with the given http.Request, without following
// any redirects, and returns the first response, which might be a redirect.
// It's basically a shorthand for c.Transport().RoundTrip(req).
func (c *Client) Trip(req *http.Request) (*Response, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(profileName).Note("TRIP-"+req.Method, req.URL.String()).End()
	}
	c.debugf("TRIP %s %s", req.Method, req.URL)
	return makeResponse(c.transport.RoundTrip(req))
}
Beispiel #2
0
// Post is a wrapper around http.Client.Post, returning a Response rather than an
// http.Response. See http.Client.Post for further details.
func (c *Client) Post(url string, bodyType string, body io.Reader) (*Response, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(profileName).Note("POST", url).End()
	}
	c.debugf("POST %s", url)
	return makeResponse(c.c.Post(url, bodyType, body))
}
Beispiel #3
0
// Do is a wrapper around http.Client.Do, returning a Response rather than an
// http.Response. See http.Client.Do for further details.
func (c *Client) Do(req *http.Request) (*Response, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(profileName).Note(req.Method, req.URL.String()).End()
	}
	c.debugf("DO %s %s", req.Method, req.URL)
	return makeResponse(c.c.Do(req))
}
Beispiel #4
0
// SetBytes stores the given byte array assocciated with
// the given key. See the documentation for Set for an
// explanation of the timeout parameter
func (c *Cache) SetBytes(key string, b []byte, timeout int) error {
	if profile.On && profile.Profiling() {
		defer profile.Start(cache).Note("SET", key).End()
	}
	if c.pipe != nil {
		var err error
		b, err = c.pipe.Encode(b)
		if err != nil {
			perr := &cacheError{
				op:  "encoding data with pipe",
				key: key,
				err: err,
			}
			c.error(perr)
			return perr
		}
	}
	k := c.backendKey(key)
	err := c.driver.Set(k, b, timeout)
	if err != nil {
		serr := &cacheError{
			op:  "setting key",
			key: key,
			err: err,
		}
		c.error(serr)
		return serr
	}
	c.debugf("Set key %s (%d bytes), expiring in %d", k, len(b), timeout)
	return nil
}
Beispiel #5
0
// Head is a wrapper around http.Client.Head, returning a Response rather than an
// http.Response. See http.Client.Head for further details.
func (c *Client) Head(url string) (*Response, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(profileName).Note("HEAD", url).End()
	}
	c.debugf("HEAD %s", url)
	return makeResponse(c.c.Head(url))
}
Beispiel #6
0
// GetBytes returns the byte array assocciated with the given key
func (c *Cache) GetBytes(key string) ([]byte, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(cache).Note("GET", key).End()
	}
	b, err := c.driver.Get(c.backendKey(key))
	if err != nil {
		gerr := &cacheError{
			op:  "getting key",
			key: key,
			err: err,
		}
		c.error(gerr)
		return nil, gerr
	}
	if b == nil {
		return nil, ErrNotFound
	}
	if c.pipe != nil {
		b, err = c.pipe.Decode(b)
		if err != nil {
			perr := &cacheError{
				op:  "decoding data with pipe",
				key: key,
				err: err,
			}
			c.error(perr)
			return nil, perr
		}
	}
	return b, nil
}
Beispiel #7
0
// Upsert tries to perform an update with the given query
// and object. If there are not affected rows, it performs
// an insert. Some drivers (like mongodb) are able to perform
// this operation in just one query, but most require two
// trips to the database.
func (o *Orm) Upsert(q query.Q, obj interface{}) (Result, error) {
	m, err := o.model(obj)
	if err != nil {
		return nil, err
	}
	if err := m.fields.Methods.Save(obj); err != nil {
		return nil, err
	}
	if o.driver.Upserts() {
		if profile.On && profile.Profiling() {
			defer profile.Start(orm).Note("upsert", "").End()
		}
		return o.conn.Upsert(m, q, obj)
	}
	res, err := o.update(m, q, obj)
	if err != nil {
		return nil, err
	}
	aff, err := res.RowsAffected()
	if err != nil {
		return nil, err
	}
	if aff == 0 {
		res, err = o.insert(m, obj)
	}
	return res, err
}
Beispiel #8
0
// Count returns the number of results for the query. Note that
// you have to set the table manually before calling Count().
func (q *Query) Count() (uint64, error) {
	if err := q.ensureTable("Count"); err != nil {
		return 0, err
	}
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("count", q.model.String()).End()
	}
	return q.orm.driver.Count(q.model, q.q, q.opts)
}
Beispiel #9
0
// Exists returns wheter a result with the specified query
// exists.
func (q *Query) Exists() (bool, error) {
	if err := q.ensureTable("Exists"); err != nil {
		return false, err
	}
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("exists", q.model.String()).End()
	}
	return q.orm.driver.Exists(q.model, q.q)
}
Beispiel #10
0
func (q *Query) exec(limit *int) driver.Iter {
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("query", q.model.String()).End()
	}
	opts := q.opts
	if limit != nil {
		opts.Limit = *limit
	}
	return q.orm.conn.Query(q.model, q.q, opts)
}
Beispiel #11
0
func (o *Orm) insert(m *model, obj interface{}) (Result, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("insert", m.name).End()
	}
	var pkName string
	var pkVal reflect.Value
	f := m.fields
	if f.AutoincrementPk {
		pkName, pkVal = o.primaryKey(f, obj)
		if pkVal.Int() == 0 && !pkVal.CanSet() {
			typ := reflect.TypeOf(obj)
			return nil, fmt.Errorf("can't set primary key field %q. Please, insert a %v rather than a %v", pkName, reflect.PtrTo(typ), typ)
		}
	}
	if f.Defaults != nil {
		val := reflect.ValueOf(obj)
		for k, v := range f.Defaults {
			indexes := f.Indexes[k]
			fval := o.fieldByIndexCreating(val, indexes)
			isTrue, _ := types.IsTrueVal(fval)
			if !isTrue {
				if !fval.CanSet() {
					// Need to copy to alter the fields
					pval := reflect.New(val.Type())
					pval.Elem().Set(val)
					obj = pval.Interface()
					val = pval
					fval = o.fieldByIndexCreating(val, indexes)
				}
				if v.Kind() == reflect.Func {
					out := v.Call(nil)
					fval.Set(out[0])
				} else {
					fval.Set(v)
				}
			}
		}
	}
	res, err := o.conn.Insert(m, obj)
	if err == nil && pkVal.IsValid() && pkVal.Int() == 0 {
		id, err := res.LastInsertId()
		if err == nil && id != 0 {
			if o.logger != nil {
				o.logger.Debugf("Setting primary key %q to %d on model %v", pkName, id, m.Type())
			}
			pkVal.SetInt(id)
		} else if err != nil && o.logger != nil {
			o.logger.Errorf("could not obtain last insert id: %s", err)
		}
	}
	return res, err
}
Beispiel #12
0
// LoadTemplate loads a template using the template
// loader and the asset manager assocciated with
// this app
func (app *App) LoadTemplate(name string) (*Template, error) {
	app.templatesMutex.RLock()
	tmpl := app.templatesCache[name]
	app.templatesMutex.RUnlock()
	if tmpl == nil {
		var err error
		log.Debugf("Loading root template %s", name)
		if profile.On && profile.Profiling() {
			defer profile.Start("template").Note("load", name).End()
		}
		tmpl, err = app.loadTemplate(app.templatesFS, app.assetsManager, name)
		if err != nil {
			return nil, err
		}
		var funcs []*template.Func
		for _, v := range app.included {
			funcs = append(funcs, &template.Func{
				Name:   v.assetFuncName(),
				Fn:     v.assetFunc(tmpl.tmpl),
				Traits: template.FuncTraitPure,
			})
		}
		tmpl.tmpl.Funcs(funcs)
		for _, v := range app.templatePlugins {
			if err := tmpl.tmpl.AddPlugin(v); err != nil {
				return nil, fmt.Errorf("error adding plugin %q: %s", v.Template.Root(), err)
			}
		}
		if profile.On {
			if profilePlugin != nil {
				tmpl.tmpl.AddPlugin(profilePlugin)
			}
		}
		if err := tmpl.prepare(); err != nil {
			return nil, err
		}
		if !app.cfg.TemplateDebug {
			app.templatesMutex.Lock()
			if app.templatesCache == nil {
				app.templatesCache = make(map[string]*Template)
			}
			app.templatesCache[name] = tmpl
			app.templatesMutex.Unlock()
		}
	}
	return tmpl, nil
}
Beispiel #13
0
func (o *Orm) save(m *model, obj interface{}) (Result, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("save", m.name).End()
	}
	var res Result
	var err error
	if m.fields.PrimaryKey >= 0 {
		pkName, pkVal := o.primaryKey(m.fields, obj)
		if driver.IsZero(pkVal) {
			return o.insert(m, obj)
		}
		res, err = o.update(m, Eq(pkName, pkVal.Interface()), obj)
	} else if len(m.fields.CompositePrimaryKey) > 0 {
		// Composite primary key
		names, values := o.compositePrimaryKey(m.fields, obj)
		for _, v := range values {
			if !driver.IsZero(v) {
				// We have a non-zero value, try to update
				qs := make([]query.Q, len(names))
				for ii := range names {
					qs[ii] = Eq(names[ii], values[ii].Interface())
				}
				res, err = o.update(m, And(qs...), obj)
				break
			}
		}
		if res == nil && err == nil {
			// Not updated. All the fields in the PK are zero
			return o.insert(m, obj)
		}
	} else {
		// No pk
		return o.insert(m, obj)
	}
	if err != nil {
		return nil, err
	}
	up, err := res.RowsAffected()
	if err != nil {
		return nil, err
	}
	if up == 0 {
		return o.insert(m, obj)
	}
	return res, nil
}
Beispiel #14
0
func (t *Template) ExecuteContext(w io.Writer, data interface{}, context interface{}, vars VarMap) error {
	if profile.On && profile.Profiling() {
		ev := profile.Start("template").Note("exec", t.qname(t.name))
		defer ev.End()
		// If the template is the final rendered template which includes
		// the profiling data, it must be ended when the timings are fetched.
		// Other templates, like asset templates, are ended by the deferred call.
		ev.AutoEnd()
	}
	buf := getBuffer()
	err := t.prog.execute(buf, t.root, data, context, vars)
	if err != nil {
		return err
	}
	if t.Minify {
		// Instead of using a new Buffer, make a copy of the []byte and Reset
		// buf. This minimizes the number of allocations while momentarily
		// using a bit more of memory than we need (exactly one byte per space
		// removed in the output).
		b := buf.Bytes()
		bc := make([]byte, len(b))
		copy(bc, b)
		r := bytes.NewReader(bc)
		buf.Reset()
		if err := html.Minify(buf, r); err != nil {
			return err
		}
	}
	if rw, ok := w.(http.ResponseWriter); ok {
		header := rw.Header()
		header.Set("Content-Type", t.contentType)
		header.Set("Content-Length", strconv.Itoa(buf.Len()))
	}
	_, err = w.Write(buf.Bytes())
	putBuffer(buf)
	return err
}
Beispiel #15
0
func (o *Orm) delete(m *model, q query.Q) (Result, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("delete", m.name).End()
	}
	return o.conn.Delete(m, q)
}
Beispiel #16
0
func (o *Orm) update(m *model, q query.Q, obj interface{}) (Result, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("update", m.name).End()
	}
	return o.conn.Update(m, q, obj)
}