package main import ( "fmt" "log" "os" "regexp" "strings" "sync" "sync/atomic" "time" "github.com/tecbot/gorocksdb" ) // EDB 全局操作的edb对象 var EDB *EasyDataBase // OpenLog 初始化日志设置 func OpenLog() { f, err := os.OpenFile("./rocksdb.log", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0660) if err != nil { panic(err) } log.SetOutput(f) } func init() { OpenLog() EDB = NewEasyDataBase() } func NewEasyDataBase() *EasyDataBase { edb := &EasyDataBase{} db, cfs := OpenDataBase() edb.DB = db edb.CFS = cfs return edb } type EasyDataBase struct { DB *gorocksdb.DB CFS gorocksdb.ColumnFamilyHandles Tables map[uint32]*Table TableDict map[string]uint32 Metadata } type Metadata struct { tidCount uint32 // int16 } type ValueType int const ( VT_BOOL ValueType = 00000 + iota ) const ( VT_INT ValueType = 10000 + iota VT_INT8 VT_INT16 VT_INT32 VT_INT64 ) const ( VT_UINT ValueType = 11000 + iota VT_UINT8 VT_UINT16 VT_UINT32 VT_UINT64 ) const ( VT_CHAR ValueType = 12000 + iota VT_VARCHAR VT_TEXT ) const ( VT_TIMESTAMP ValueType = 13000 + iota VT_DATE ) type Field struct { Key []byte VT ValueType ID uint16 IsIndex bool IsUnique bool } // Parse 从字符串中解析 var a int; a = 0; a < 0 && a > 5 ; func (field *Field) Parse(code string) { codes := strings.Split(code, ";") re := regexp.MustCompile("var +([a-zA-Z_]+) +[a-zA-Z]+[8|16|32|64]{0,1}") re.FindStringSubmatch(codes[0]) } // Table 表结构 type Table struct { tableLock *sync.Mutex Name string Type int ID uint32 // uint16 IsAllKey bool Fields []*Field fidCount uint16 // uint16 idxCount uint64 rawCount uint64 delCount uint64 } // CreateField 创建字段 func (table *Table) CreateField(key []byte, vt ValueType, isIndex bool, isUnique bool) *Field { table.tableLock.Lock() defer table.tableLock.Unlock() field := &Field{} field.ID = table.fidCount field.IsIndex = isIndex field.IsUnique = isUnique field.Key = key field.VT = vt table.fidCount++ return field } // CreateTable 创建表 func CreateTable(name string, fields []*Field) { if _, ok := EDB.TableDict[name]; !ok { ntid := atomic.AddUint32(&EDB.Metadata.tidCount, 1) table := &Table{Name: name, ID: ntid, Type: 1} table.Fields = fields } else { log.Println("table name is exists") } } // OpenDataBase (cf-key.{tableid(2)}{fieldid(2)}) {value}{indexid(6)} = {rowid(6)} (cf-row.{tableid(2)} {row-sharding-id}){rowid(6)} = {values} func OpenDataBase() (*gorocksdb.DB, []*gorocksdb.ColumnFamilyHandle) { bbto := gorocksdb.NewDefaultBlockBasedTableOptions() bbto.SetBlockCache(gorocksdb.NewLRUCache(3 << 30)) bbto.SetCacheIndexAndFilterBlocksWithHighPriority(true) opts := gorocksdb.NewDefaultOptions() bbto.SetFilterPolicy(gorocksdb.NewBloomFilter(16)) opts.SetBlockBasedTableFactory(bbto) opts.SetCreateIfMissing(true) opts.SetCreateIfMissingColumnFamilies(true) opts.SetCompression(gorocksdb.LZ4Compression) year, month, day := time.Now().Date() timeCFStr := fmt.Sprintf("%d-%d-%d", year, int64(month), day) log.Println(timeCFStr) names, err := gorocksdb.ListColumnFamilies(opts, ".rocksdb") if err != nil { log.Println(".rocksdb 文件不存在") names = append(names, "default") } isadd := true var opslist []*gorocksdb.Options for _, name := range names { opslist = append(opslist, opts) if timeCFStr == name { isadd = false } } if isadd { names = append(names, timeCFStr) opslist = append(opslist, opts) } log.Println("ListColumnFamilies:", names) db, cfs, err := gorocksdb.OpenDbColumnFamilies(opts, ".rocksdb", names, opslist) if err != nil { panic(err) } return db, cfs }