Example #1
0
func (db *DB) _raw_ssttlat_put(ns byte, key []byte, ttlat uint64) bool {

	if ttlat == 0 {
		return true
	}

	key = skv.RawNsKeyConcat(ns, key)

	batch := new(leveldb.Batch)

	//
	if prev := db.RawGet(skv.RawTtlEntry(key)); prev.Status == skv.ReplyOK {
		if prev_ttlat := dbutil.BytesToUint64(prev.Bytes()); prev_ttlat != ttlat {
			batch.Delete(skv.RawTtlQueue(key, prev_ttlat))
		}
	}

	//
	batch.Put(skv.RawTtlQueue(key, ttlat), []byte{})

	//
	batch.Put(skv.RawTtlEntry(key), dbutil.Uint64ToBytes(ttlat))

	if err := db.ldb.Write(batch, nil); err != nil {
		return false
	}

	return true
}
Example #2
0
func (db *DB) _raw_ssttl_get(ns byte, key []byte) *skv.Reply {

	key = skv.RawNsKeyConcat(ns, key)

	rpl, ttl := skv.NewReply(""), int64(0)

	if ttlat := dbutil.BytesToUint64(db.RawGet(skv.RawTtlEntry(key)).Bytes()); ttlat > 0 {
		ttl = (dbutil.MetaTimeParse(ttlat).UnixNano() - time.Now().UTC().UnixNano()) / 1e6
	}

	if ttl < 0 {
		ttl = 0
	}

	rpl.Data = append(rpl.Data, []byte(strconv.FormatInt(ttl, 10)))

	return rpl
}
Example #3
0
File: ttl.go Project: lessos/lessdb
func (db *DB) ttl_worker() {

	go func() {

		for {

			ls := db._raw_ssttlat_range(0, dbutil.MetaTimeNow(), _ttl_worker_limit).Hash()

			for _, v := range ls {

				batch := new(leveldb.Batch)

				if dbutil.BytesToUint64(db.RawGet(skv.RawTtlEntry(v.Key[9:])).Bytes()) == v.Uint64() {

					batch.Delete(skv.RawTtlEntry(v.Key[9:]))

					switch v.Key[9] {

					case skv.NsObjectEntry:
						db.ObjectDel(string(v.Key[10:]))

					case skv.NsKvEntry:
						batch.Delete(v.Key[9:])
					}
				}

				batch.Delete(v.Key)

				db.ldb.Write(batch, nil)
			}

			if uint64(len(ls)) < _ttl_worker_limit {
				time.Sleep(_ttl_worker_sleep)
			}
		}
	}()
}
Example #4
0
func (db *DB) ObjectDocPut(fold, key string, obj interface{}, opts *skv.ObjectWriteOptions) *skv.Reply {

	_obj_doc_global_locker.Lock()
	_obj_doc_global_locker.Unlock()

	var (
		opath = skv.NewObjectPathKey(fold, key)
		rpl   = skv.NewReply("")
	)

	if len(opath.Fold) > skv.ObjectDocKeyLenMax ||
		len(opath.Field) > skv.ObjectDocPriLenMax ||
		obj == nil {
		rpl.Status = skv.ReplyBadArgument
		return rpl
	}

	var (
		bkey    = opath.EntryIndex()
		objt    = reflect.TypeOf(obj)
		objv    = reflect.ValueOf(obj)
		prev    = map[string]interface{}{}
		previdx = map[uint8]skv.ObjectDocSchemaIndexEntryBytes{}
		set     = map[string]interface{}{}
	)

	if opts == nil {
		opts = _obj_options_def
	}

	prevobj := db.RawGet(bkey).Object()
	if prevobj.Status == skv.ReplyOK {

		if err := prevobj.Data.JsonDecode(&prev); err == nil {
			previdx = skv.ObjectDocIndexDataExport(_obj_doc_indexes, opath.Fold, prev)
		}
	}

	if objt.Kind() == reflect.Struct {

		for i := 0; i < objt.NumField(); i++ {
			set[skv.ObjectDocIndexStringFilter(objt.Field(i).Name)] = objv.Field(i).Interface()
		}

	} else if objt.Kind() == reflect.Map {

		mks := objv.MapKeys()

		for _, mkv := range mks {

			if mkv.Kind() == reflect.String {
				set[skv.ObjectDocIndexStringFilter(mkv.String())] = objv.MapIndex(mkv).Interface()
			}
		}

	} else {

		rpl.Status = skv.ReplyBadArgument
		return rpl
	}

	setidx, idxnew, idxdup := skv.ObjectDocIndexDataExport(_obj_doc_indexes, opath.Fold, set), [][]byte{}, [][]byte{}

	// fmt.Println("\tsetidx", setidx)
	// fmt.Println("\tprevidx", previdx)

	for siKey, siEntry := range setidx {

		var incr_set, incr_prev uint64

		if siEntry.AutoIncr {
			incr_set = dbutil.BytesToUint64(siEntry.Data)
		}

		//
		if piEntry, ok := previdx[siKey]; ok {

			if siEntry.AutoIncr && incr_set == 0 {

				if incr_prev = dbutil.BytesToUint64(piEntry.Data); incr_prev > 0 {

					siEntry.Data, incr_set = piEntry.Data, incr_prev

					set[siEntry.FieldName] = incr_set

					continue
				}

			} else if bytes.Compare(piEntry.Data, siEntry.Data) == 0 {
				continue
			}

			idxdup = append(idxdup, append(append(skv.ObjectDocIndexFieldPrefix(opath.Fold, siKey), piEntry.Data...), opath.Field...))
		}

		//
		if siEntry.AutoIncr {

			if incr_set == 0 {

				incr_set = db.RawIncrby(skv.ObjectDocIndexIncrKey(opath.Fold, siEntry.Seq), 1).Uint64()

				ibs := make([]byte, 8)
				binary.BigEndian.PutUint64(ibs, incr_set)

				siEntry.Data = ibs[(8 - len(siEntry.Data)):]

				set[siEntry.FieldName] = incr_set

			} else if incr_set > 0 && incr_set > incr_prev {

				if db.RawGet(skv.ObjectDocIndexIncrKey(opath.Fold, siEntry.Seq)).Uint64() < incr_set {
					db.RawPut(skv.ObjectDocIndexIncrKey(opath.Fold, siEntry.Seq), []byte(strconv.FormatUint(incr_set, 10)), 0)
				}
			}
		}

		if siEntry.Unique || siEntry.AutoIncr {

			objIdxKeyPrefix := append(skv.ObjectDocIndexFieldPrefix(opath.Fold, siKey), siEntry.Data...)

			if rs := db.RawScan(objIdxKeyPrefix, []byte{}, 1).Hash(); len(rs) > 0 {
				rpl.Status = skv.ReplyBadArgument
				return rpl
			}
		}

		idxnew = append(idxnew, append(append(skv.ObjectDocIndexFieldPrefix(opath.Fold, siKey), siEntry.Data...), opath.Field...))
	}

	//

	//
	batch := new(leveldb.Batch)

	for _, idxkey := range idxdup {
		batch.Delete(idxkey)
	}

	for _, idxkey := range idxnew {
		batch.Put(idxkey, []byte{})
	}

	bvalue, _ := dbutil.JsonEncode(set)
	sum := crc32.ChecksumIEEE(bvalue)

	if prevobj.Meta.Sum == sum {
		return skv.NewReply(skv.ReplyOK)
	}

	db._obj_meta_sync(skv.ObjectTypeDocument, &prevobj.Meta, opath, int64(len(bvalue)), sum, _obj_options_def)

	batch.Put(bkey, append(prevobj.Meta.Export(), bvalue...))

	if err := db.ldb.Write(batch, nil); err != nil {
		rpl.Status = err.Error()
	}

	return rpl
}