From f0531b17e9fc7dc5630cb2b9bab7c59443deb811 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Fri, 1 Jun 2018 12:20:04 +0200 Subject: [PATCH 01/10] core-metadata: Add db interface Signed-off-by: Federico Claramonte --- core/domain/enums/database.go | 16 +- core/domain/enums/database_test.go | 6 +- core/domain/models/adminstate.go | 13 +- core/domain/models/operatingstate.go | 12 +- core/metadata/const.go | 19 +- core/metadata/dbOps.go | 697 +++-------------- core/metadata/init.go | 20 +- core/metadata/mongoOps.go | 958 +++++++++++------------- core/metadata/mongo_device.go | 11 +- core/metadata/mongo_deviceprofile.go | 6 +- core/metadata/mongo_deviceservice.go | 6 +- core/metadata/mongo_provisionwatcher.go | 8 +- core/metadata/mongo_scheduleevent.go | 6 +- core/metadata/rest_addressable.go | 38 +- core/metadata/rest_command.go | 20 +- core/metadata/rest_device.go | 188 ++--- core/metadata/rest_deviceprofile.go | 46 +- core/metadata/rest_devicereport.go | 36 +- core/metadata/rest_deviceservice.go | 103 +-- core/metadata/rest_provisionwatcher.go | 50 +- core/metadata/rest_scheduleevent.go | 82 +- 21 files changed, 895 insertions(+), 1446 deletions(-) diff --git a/core/domain/enums/database.go b/core/domain/enums/database.go index f47ec6d118..a488c0148d 100644 --- a/core/domain/enums/database.go +++ b/core/domain/enums/database.go @@ -22,20 +22,20 @@ type DATABASE int const ( INVALID DATABASE = iota MONGODB - MYSQL + MEMORYDB ) const ( invalidStr = "invalid" - mongoStr = "mongodb" - mysqlStr = "mysql" + MongoStr = "mongodb" + MemoryStr = "memorydb" ) // DATABASEArr : Add in order declared in Struct for string value -var databaseArr = [...]string{invalidStr, mongoStr, mysqlStr} +var databaseArr = [...]string{invalidStr, MongoStr, MemoryStr} func (db DATABASE) String() string { - if db >= INVALID && db <= MYSQL { + if db >= INVALID && db <= MEMORYDB { return databaseArr[db] } return invalidStr @@ -43,10 +43,10 @@ func (db DATABASE) String() string { // GetDatabaseType : Return enum valude of the Database Type func GetDatabaseType(db string) (DATABASE, error) { - if mongoStr == db { + if MongoStr == db { return MONGODB, nil - } else if mysqlStr == db { - return MYSQL, nil + } else if MemoryStr == db { + return MEMORYDB, nil } else { return INVALID, errors.New("Undefined Database Type") } diff --git a/core/domain/enums/database_test.go b/core/domain/enums/database_test.go index 53e7337b6c..f6ed783835 100644 --- a/core/domain/enums/database_test.go +++ b/core/domain/enums/database_test.go @@ -25,7 +25,7 @@ func TestGetDatabaseType(t *testing.T) { wantErr bool }{ {"type is mongo", "mongodb", MONGODB, false}, - {"type is mysql", "mysql", MYSQL, false}, + {"type is memorydb", "memorydb", MEMORYDB, false}, {"type is unknown", "foo", INVALID, true}, } for _, tt := range tests { @@ -48,10 +48,10 @@ func TestStringDatabaseType(t *testing.T) { db DATABASE }{ {"mongo", MONGODB}, - {"mysql", MYSQL}, + {"memory", MEMORYDB}, {"unknown", INVALID}, {"invalid1", INVALID - 1}, - {"invalid2", MYSQL + 1}, + {"invalid2", MEMORYDB + 1}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/core/domain/models/adminstate.go b/core/domain/models/adminstate.go index 6940f0c06d..9cc54a02df 100644 --- a/core/domain/models/adminstate.go +++ b/core/domain/models/adminstate.go @@ -48,11 +48,14 @@ func (as *AdminState) UnmarshalJSON(data []byte) error { *as = got return nil } + func IsAdminStateType(as string) bool { + _, found := GetAdminState(as) + return found +} + +func GetAdminState(as string) (AdminState, bool) { as = strings.ToUpper(as) - _, err := map[string]AdminState{"LOCKED": Locked, "UNLOCKED": Unlocked}[as] - if !err { - return false - } - return true + retValue, err := map[string]AdminState{"LOCKED": Locked, "UNLOCKED": Unlocked}[as] + return retValue, err } diff --git a/core/domain/models/operatingstate.go b/core/domain/models/operatingstate.go index d74755f2e8..bb70a6f5d2 100644 --- a/core/domain/models/operatingstate.go +++ b/core/domain/models/operatingstate.go @@ -51,10 +51,12 @@ func (os *OperatingState) UnmarshalJSON(data []byte) error { // IsOperatingStateType : return if ostype func IsOperatingStateType(os string) bool { + _, found := GetOperatingState(os) + return found +} + +func GetOperatingState(os string) (OperatingState, bool) { os = strings.ToUpper(os) - _, err := map[string]OperatingState{"ENABLED": Enabled, "DISABLED": Disabled}[os] - if !err { - return false - } - return true + o, err := map[string]OperatingState{"ENABLED": Enabled, "DISABLED": Disabled}[os] + return o, err } diff --git a/core/metadata/const.go b/core/metadata/const.go index c0be8d012a..a2042cd46e 100644 --- a/core/metadata/const.go +++ b/core/metadata/const.go @@ -15,8 +15,6 @@ package metadata import ( "errors" - - "github.com/edgexfoundry/edgex-go/core/domain/enums" ) // Struct used to pase the JSON configuration file @@ -59,14 +57,13 @@ var configuration ConfigurationStruct = ConfigurationStruct{} // Needs to be ini var ( /* -------------- CONFIG for METADATA -------------------- */ - DATABASE enums.DATABASE - DBTYPE = "mongodb" - PROTOCOL = "http" - SERVERPORT = "48081" - DOCKERMONGO = "edgex-mongo:27017" - DBUSER = "meta" - DBPASS = "password" - MONGODATABASE = "metadata" + db DBClient + PROTOCOL = "http" + SERVERPORT = "48081" + DOCKERMONGO = "edgex-mongo:27017" + DBUSER = "meta" + DBPASS = "password" + MONGODATABASE = "metadata" MAX_LIMIT int = 1000 @@ -101,7 +98,7 @@ var ( ADDRESSABLE = "addressable" ADDRESSABLENAME = "addressablename" ADDRESSABLEID = "addressableid" - CHECK = "check" + CHECK = "check" SERVICE = "service" SERVICENAME = "servicename" SERVICEID = "serviceid" diff --git a/core/metadata/dbOps.go b/core/metadata/dbOps.go index 3d76dda0db..d30e13daf0 100644 --- a/core/metadata/dbOps.go +++ b/core/metadata/dbOps.go @@ -14,595 +14,114 @@ package metadata import ( - "time" - - enums "github.com/edgexfoundry/edgex-go/core/domain/enums" - models "github.com/edgexfoundry/edgex-go/core/domain/models" - mgo "gopkg.in/mgo.v2" - bson "gopkg.in/mgo.v2/bson" + "github.com/edgexfoundry/edgex-go/core/domain/enums" + "github.com/edgexfoundry/edgex-go/core/domain/models" ) -type DataStore struct { - s *mgo.Session -} - -func (ds DataStore) dataStore() *DataStore { - return &DataStore{ds.s.Copy()} -} - -// Connect to the database -func dbConnect() bool { - if DATABASE == enums.MONGODB { - - mongoDBDialInfo := &mgo.DialInfo{ - Addrs: []string{DOCKERMONGO}, - Timeout: time.Duration(configuration.MongoDBConnectTimeout) * time.Millisecond, - Database: MONGODATABASE, - Username: DBUSER, - Password: DBPASS, - } - s, err := mgo.DialWithInfo(mongoDBDialInfo) - if err != nil { - return false - } - - // Set timeout based on configuration - s.SetSocketTimeout(time.Duration(configuration.MongoDBConnectTimeout) * time.Millisecond) - DS.s = s - return true - } - return false -} - -/* ----------------------- Schedule Event ------------------------------*/ -func getAllScheduleEvents(se *[]models.ScheduleEvent) error { - if DATABASE == enums.MONGODB { - return mgoGetAllScheduleEvents(se) - } - return nil -} -func addScheduleEvent(se *models.ScheduleEvent) error { - if DATABASE == enums.MONGODB { - return mgoAddScheduleEvent(se) - } - return nil -} -func getScheduleEventByName(se *models.ScheduleEvent, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleEventByName(se, n) - } - return nil -} -func updateScheduleEvent(se models.ScheduleEvent) error { - if DATABASE == enums.MONGODB { - return mgoUpdateScheduleEvent(se) - } - return nil -} -func getScheduleEventById(se *models.ScheduleEvent, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleEventById(se, id) - } - return nil -} -func getScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleEventsByScheduleName(se, n) - } - return nil -} -func getScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleEventsByAddressableId(se, id) - } - return nil -} -func getScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleEventsByServiceName(se, n) - } - return nil -} - -/* -------------------------- Schedule ---------------------------------*/ -func getAllSchedules(s *[]models.Schedule) error { - if DATABASE == enums.MONGODB { - return mgoGetAllSchedules(s) - } - return nil -} -func addSchedule(s *models.Schedule) error { - if DATABASE == enums.MONGODB { - return mgoAddSchedule(s) - } - return nil -} -func getScheduleByName(s *models.Schedule, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleByName(s, n) - } - return nil -} -func updateSchedule(s models.Schedule) error { - if DATABASE == enums.MONGODB { - return mgoUpdateSchedule(s) - } - return nil -} -func getScheduleById(s *models.Schedule, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetScheduleById(s, id) - } - return nil -} - -/* ------------------------Device Report -------------------------------*/ -func getAllDeviceReports(dr *[]models.DeviceReport) error { - if DATABASE == enums.MONGODB { - return mgoGetAllDeviceReports(dr) - } - return nil -} -func getDeviceReportByDeviceName(dr *[]models.DeviceReport, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceReportByDeviceName(dr, n) - } - return nil -} -func getDeviceReportByName(dr *models.DeviceReport, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceReportByName(dr, n) - } - return nil -} -func getDeviceReportById(dr *models.DeviceReport, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceReportById(dr, id) - } - return nil -} -func addDeviceReport(dr *models.DeviceReport) error { - if DATABASE == enums.MONGODB { - return mgoAddDeviceReport(dr) - } - return nil -} -func updateDeviceReport(dr *models.DeviceReport) error { - if DATABASE == enums.MONGODB { - return mgoUpdateDeviceReport(dr) - } - return nil -} -func getDeviceReportsByScheduleEventName(dr *[]models.DeviceReport, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceReportsByScheduleEventName(dr, n) - } - return nil -} - -// ------------------------------------- DEVICE -------------------------------------------- - -func UpdateDevice(d models.Device) error { - if DATABASE == enums.MONGODB { - return mgoUpdateDevice(d) - } - return nil -} -func getDeviceById(d *models.Device, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceById(d, id) - } - return nil -} -func getDeviceByName(d *models.Device, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceByName(d, n) - } - return nil -} -func getAllDevices(d *[]models.Device) error { - if DATABASE == enums.MONGODB { - return mgoGetAllDevices(d) - } - return nil -} -func getDevicesByProfileId(d *[]models.Device, pid string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesByProfileId(d, pid) - } - return nil -} -func getDevicesByProfileName(d *[]models.Device, pn string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesByProfileName(d, pn) - } - return nil -} -func getDevicesByServiceId(d *[]models.Device, sid string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesByServiceId(d, sid) - } - return nil -} -func getDevicesByServiceName(d *[]models.Device, sn string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesByServiceName(d, sn) - } - return nil -} -func getDevicesByAddressableId(d *[]models.Device, aid string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesByAddressableId(d, aid) - } - return nil -} -func getDevicesByAddressableName(d *[]models.Device, an string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesByAddressableName(d, an) - } - return nil -} -func getDevicesWithLabel(d *[]models.Device, l []string) error { - if DATABASE == enums.MONGODB { - return mgoGetDevicesWithLabel(d, l) - } - return nil -} -func addDevice(d *models.Device) error { - if DATABASE == enums.MONGODB { - return mgoAddNewDevice(d) - } - return nil -} -func updateDeviceProfile(dp *models.DeviceProfile) error { - if DATABASE == enums.MONGODB { - return mgoUpdateDeviceProfile(dp) - } - return nil -} -func addDeviceProfile(d *models.DeviceProfile) error { - if DATABASE == enums.MONGODB { - return mgoAddNewDeviceProfile(d) - } - return nil -} -func getAllDeviceProfiles(d *[]models.DeviceProfile) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfiles(d, bson.M{}) - } - return nil -} -func getDeviceProfileById(d *models.DeviceProfile, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfileById(d, id) - } - return nil -} -func deleteDeviceProfileById(dpid string) error { - if err := deleteById(DPCOL, dpid); err != nil { - return err - } - return nil -} -func deleteDeviceProfileByName(n string) error { - var dp models.DeviceProfile - getDeviceProfileByName(&dp, n) - // Delete all of the commands for the device profile - for i := 0; i < len(dp.Commands); i++ { - // TODO Figure out how to store MONGO ID - if err := deleteById(COMCOL, dp.Commands[i].Id.Hex()); err != nil { - return err - } - } - // Delete the device profile - if err := deleteByName(DPCOL, n); err != nil { - return err - } - return nil -} - -func getDeviceProfilesByModel(dp *[]models.DeviceProfile, m string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfilesByModel(dp, m) - } - return nil -} -func getDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfilesWithLabel(dp, l) - } - return nil -} -func getDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfilesByManufacturerModel(dp, man, mod) - } - return nil -} -func getDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfilesByManufacturer(dp, man) - } - return nil -} -func getDeviceProfileByName(dp *models.DeviceProfile, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfileByName(dp, n) - } - return nil -} -func updateAddressable(ra *models.Addressable, r *models.Addressable) error { - if DATABASE == enums.MONGODB { - return mgoUpdateAddressable(ra, r) - } - return nil -} -func addAddressable(a *models.Addressable) error { - if DATABASE == enums.MONGODB { - return mgoAddNewAddressable(a) - } - return nil -} -func getAddressableById(a *models.Addressable, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressableById(a, id) - } - return nil -} -func getAddressableByName(a *models.Addressable, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressableByName(a, n) - } - return nil -} -func getAddressablesByTopic(a *[]models.Addressable, t string) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressablesByTopic(a, t) - } - return nil -} -func getAddressablesByPort(a *[]models.Addressable, p int) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressablesByPort(a, p) - } - return nil -} -func getAddressablesByPublisher(a *[]models.Addressable, p string) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressablesByPublisher(a, p) - } - return nil -} -func getAddressablesByAddress(a *[]models.Addressable, add string) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressablesByAddress(a, add) - } - return nil -} -func getAddressable(d *models.Addressable, q bson.M) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressable(d, q) - } - return nil -} -func getAddressables(d *[]models.Addressable, q bson.M) error { - if DATABASE == enums.MONGODB { - return mgoGetAddressables(d, q) - } - return nil -} -func isAddressableAssociatedToDevice(a models.Addressable) (bool, error) { - if DATABASE == enums.MONGODB { - return mgoIsAddressableAssociatedToDevice(a) - } - return false, nil -} -func isAddressableAssociatedToDeviceService(a models.Addressable) (bool, error) { - if DATABASE == enums.MONGODB { - return mgoIsAddressableAssociatedToDeviceService(a) - } - return false, nil -} - -// ------------------------ DEVICE SERVICE ----------------------- - -func updateDeviceService(ds models.DeviceService) error { - if DATABASE == enums.MONGODB { - return mgoUpdateDeviceService(ds) - } - return nil -} -func getDeviceServicesByAddressableName(d *[]models.DeviceService, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceServicesByAddressableName(d, n) - } - return nil -} -func getDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceServicesByAddressableId(d, id) - } - return nil -} -func getDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceServicesWithLabel(d, l) - } - return nil -} -func getDeviceServiceById(d *models.DeviceService, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceServiceById(d, id) - } - return nil -} -func getDeviceServiceByName(d *models.DeviceService, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceServiceByName(d, n) - } - return nil -} -func getAllDeviceServices(d *[]models.DeviceService) error { - if DATABASE == enums.MONGODB { - return mgoGetAllDeviceServices(d) - } - return nil -} -func addDeviceService(ds *models.DeviceService) error { - if DATABASE == enums.MONGODB { - return mgoAddNewDeviceService(ds) - } - return nil -} - -/* -----------------------Provision Watcher ----------------------*/ -func getProvisionWatcherById(pw *models.ProvisionWatcher, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatcherById(pw, id) - } - return nil -} -func getAllProvisionWatchers(pw *[]models.ProvisionWatcher) error { - if DATABASE == enums.MONGODB { - return mgoGetAllProvisionWatchers(pw) - } - return nil -} -func getProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatcherByName(pw, n) - } - return nil -} -func getProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatcherByProfileId(pw, id) - } - return nil -} -func getProvisionWatchersByProfileName(pw *[]models.ProvisionWatcher, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatchersByProfileName(pw, n) - } - return nil -} -func getProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatchersByServiceId(pw, id) - } - return nil -} -func getProvisionWatchersByServiceName(pw *[]models.ProvisionWatcher, n string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatchersByServiceName(pw, n) - } - return nil -} -func getProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error { - if DATABASE == enums.MONGODB { - return mgoGetProvisionWatchersByIdentifier(pw, k, v) - } - return nil -} -func addProvisionWatcher(pw *models.ProvisionWatcher) error { - if DATABASE == enums.MONGODB { - return mgoAddProvisionWatcher(pw) - } - return nil -} -func updateProvisionWatcher(pw models.ProvisionWatcher) error { - if DATABASE == enums.MONGODB { - return mgoUpdateProvisionWatcher(pw) - } - return nil -} - -/* -----------------------COMMAND ----------------------*/ -func getCommandById(c *models.Command, id string) error { - if DATABASE == enums.MONGODB { - err := mgoGetCommandById(c, id) - if err == mgo.ErrNotFound { - return ErrNotFound - } else { - return err - } - } - return nil -} -func getCommandByName(d *[]models.Command, id string) error { - if DATABASE == enums.MONGODB { - return mgoGetCommandByName(d, id) - } - return nil -} -func addCommand(c *models.Command) error { - if DATABASE == enums.MONGODB { - return mgoAddCommand(c) - } - return nil -} -func getAllCommands(d *[]models.Command) error { - if DATABASE == enums.MONGODB { - return mgoGetAllCommands(d) - } - return nil -} -func updateCommand(c *models.Command, r *models.Command) error { - if DATABASE == enums.MONGODB { - return mgoUpdateCommand(c, r) - } - return nil -} -func deleteByName(c string, n string) error { - if DATABASE == enums.MONGODB { - return mgoDeleteByName(c, n) - } - return nil -} -func deleteCommandById(id string) error { - if DATABASE == enums.MONGODB { - return mgoDeleteCommandById(id) - } - - return nil -} - -// Get the device profiles that are using the command -func getDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error { - if DATABASE == enums.MONGODB { - return mgoGetDeviceProfilesUsingCommand(dp, c) - } - - return nil -} -func deleteById(c string, did string) error { - if DATABASE == enums.MONGODB { - return mgoDeleteById(c, did) - } - return nil - -} -func setByName(c string, n string, pv2 string, p2 string) error { - if DATABASE == enums.MONGODB { - return mgoUpdateByName(c, n, pv2, p2) - } - return nil -} -func setByNameInt(c string, n string, pv2 string, p2 int64) error { - if DATABASE == enums.MONGODB { - return mgoUpdateByNameInt(c, n, pv2, p2) - } - return nil -} -func setById(c string, did string, pv2 string, p2 string) error { - if DATABASE == enums.MONGODB { - return mgoUpdateById(c, did, pv2, p2) - } - return nil -} -func setByIdInt(c string, did string, pv2 string, p2 int64) error { - if DATABASE == enums.MONGODB { - return mgoUpdateByIdInt(c, did, pv2, p2) - } - return nil +type DBClient interface { + CloseSession() + + Connect() error + + // Schedule event + getAllScheduleEvents(se *[]models.ScheduleEvent) error + addScheduleEvent(se *models.ScheduleEvent) error + getScheduleEventByName(se *models.ScheduleEvent, n string) error + updateScheduleEvent(se models.ScheduleEvent) error + getScheduleEventById(se *models.ScheduleEvent, id string) error + getScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error + getScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error + getScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error + deleteScheduleEvent(se models.ScheduleEvent) error + + // Schedule + getAllSchedules(s *[]models.Schedule) error + addSchedule(s *models.Schedule) error + getScheduleByName(s *models.Schedule, n string) error + updateSchedule(s models.Schedule) error + getScheduleById(s *models.Schedule, id string) error + deleteSchedule(s models.Schedule) error + + // Device Report + getAllDeviceReports(dr *[]models.DeviceReport) error + getDeviceReportByDeviceName(dr *[]models.DeviceReport, n string) error + getDeviceReportByName(dr *models.DeviceReport, n string) error + getDeviceReportById(dr *models.DeviceReport, id string) error + addDeviceReport(dr *models.DeviceReport) error + updateDeviceReport(dr *models.DeviceReport) error + getDeviceReportsByScheduleEventName(dr *[]models.DeviceReport, n string) error + deleteDeviceReport(dr models.DeviceReport) error + + // Device + updateDevice(d models.Device) error + getDeviceById(d *models.Device, id string) error + getDeviceByName(d *models.Device, n string) error + getAllDevices(d *[]models.Device) error + getDevicesByProfileId(d *[]models.Device, pid string) error + getDevicesByServiceId(d *[]models.Device, sid string) error + getDevicesByAddressableId(d *[]models.Device, aid string) error + getDevicesWithLabel(d *[]models.Device, l []string) error + addDevice(d *models.Device) error + deleteDevice(d models.Device) error + updateDeviceProfile(dp *models.DeviceProfile) error + addDeviceProfile(d *models.DeviceProfile) error + getAllDeviceProfiles(d *[]models.DeviceProfile) error + getDeviceProfileById(d *models.DeviceProfile, id string) error + deleteDeviceProfile(dp models.DeviceProfile) error + getDeviceProfilesByModel(dp *[]models.DeviceProfile, m string) error + getDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error + getDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error + getDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error + getDeviceProfileByName(dp *models.DeviceProfile, n string) error + + updateAddressable(ra *models.Addressable, r *models.Addressable) error + addAddressable(a *models.Addressable) error + getAddressableById(a *models.Addressable, id string) error + getAddressableByName(a *models.Addressable, n string) error + getAddressablesByTopic(a *[]models.Addressable, t string) error + getAddressablesByPort(a *[]models.Addressable, p int) error + getAddressablesByPublisher(a *[]models.Addressable, p string) error + getAddressablesByAddress(a *[]models.Addressable, add string) error + getAddressables(d *[]models.Addressable) error + deleteAddressable(a models.Addressable) error + + // Device service + updateDeviceService(ds models.DeviceService) error + getDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error + getDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error + getDeviceServiceById(d *models.DeviceService, id string) error + getDeviceServiceByName(d *models.DeviceService, n string) error + getAllDeviceServices(d *[]models.DeviceService) error + addDeviceService(ds *models.DeviceService) error + deleteDeviceService(ds models.DeviceService) error + + // Provision watcher + getProvisionWatcherById(pw *models.ProvisionWatcher, id string) error + getAllProvisionWatchers(pw *[]models.ProvisionWatcher) error + getProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error + getProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error + getProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error + getProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error + addProvisionWatcher(pw *models.ProvisionWatcher) error + updateProvisionWatcher(pw models.ProvisionWatcher) error + deleteProvisionWatcher(pw models.ProvisionWatcher) error + + // Command + getCommandById(c *models.Command, id string) error + getCommandByName(d *[]models.Command, id string) error + addCommand(c *models.Command) error + getAllCommands(d *[]models.Command) error + updateCommand(c *models.Command, r *models.Command) error + deleteCommandById(id string) error + + getDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error +} + +func getDatabase(dbType string) (DBClient, error) { + switch dbType { + case enums.MongoStr: + return &mongoDB{}, nil + case enums.MemoryStr: + } + return nil, ErrNotFound } diff --git a/core/metadata/init.go b/core/metadata/init.go index 70d522de37..12f19629c1 100644 --- a/core/metadata/init.go +++ b/core/metadata/init.go @@ -18,15 +18,12 @@ import ( "strconv" "strings" - enums "github.com/edgexfoundry/edgex-go/core/domain/enums" + "github.com/edgexfoundry/edgex-go/internal" consulclient "github.com/edgexfoundry/edgex-go/support/consul-client" logger "github.com/edgexfoundry/edgex-go/support/logging-client" notifications "github.com/edgexfoundry/edgex-go/support/notifications-client" - "github.com/edgexfoundry/edgex-go/internal" ) -// DS : DataStore to retrieve data from database. -var DS DataStore var loggingClient logger.LoggingClient func ConnectToConsul(conf ConfigurationStruct) error { @@ -60,7 +57,7 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient) error { MONGODATABASE = configuration.MongoDatabaseName PROTOCOL = configuration.Protocol SERVERPORT = strconv.Itoa(configuration.ServicePort) - DBTYPE = configuration.DBType + dbType := configuration.DBType DOCKERMONGO = configuration.MongoDBHost + ":" + strconv.Itoa(configuration.MongoDBPort) DBUSER = configuration.MongoDBUserName DBPASS = configuration.MongoDBPassword @@ -70,20 +67,17 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient) error { var err error // Connect to the database - DATABASE, err = enums.GetDatabaseType(DBTYPE) + db, err = getDatabase(dbType) if err != nil { return err } - if !dbConnect() { - return err - } - return nil + return db.Connect() } func Destruct() { - if DS.s != nil { - DS.s.Close() + if db != nil { + db.CloseSession() + db = nil } } - diff --git a/core/metadata/mongoOps.go b/core/metadata/mongoOps.go index 5b5ba58c68..bf2cb88dfc 100644 --- a/core/metadata/mongoOps.go +++ b/core/metadata/mongoOps.go @@ -15,7 +15,6 @@ package metadata import ( "errors" - "reflect" "time" "github.com/edgexfoundry/edgex-go/core/domain/models" @@ -27,11 +26,46 @@ func makeTimestamp() int64 { return time.Now().UnixNano() / int64(time.Millisecond) } +type mongoDB struct { + s *mgo.Session +} + +func getMongoSessionCopy() *mgo.Session { + m := db.(*mongoDB) + return m.s.Copy() +} + +func (m *mongoDB) Connect() error { + mongoDBDialInfo := &mgo.DialInfo{ + Addrs: []string{DOCKERMONGO}, + Timeout: time.Duration(configuration.MongoDBConnectTimeout) * time.Millisecond, + Database: MONGODATABASE, + Username: DBUSER, + Password: DBPASS, + } + var err error + m.s, err = mgo.DialWithInfo(mongoDBDialInfo) + if err != nil { + return err + } + + // Set timeout based on configuration + m.s.SetSocketTimeout(time.Duration(configuration.MongoDBConnectTimeout) * time.Millisecond) + return nil +} + +func (m *mongoDB) CloseSession() { + if m.s != nil { + m.s.Close() + m.s = nil + } +} + /* -----------------------Schedule Event ------------------------*/ -func mgoUpdateScheduleEvent(se models.ScheduleEvent) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SECOL) +func (m *mongoDB) updateScheduleEvent(se models.ScheduleEvent) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SECOL) se.Modified = makeTimestamp() @@ -40,10 +74,11 @@ func mgoUpdateScheduleEvent(se models.ScheduleEvent) error { return col.UpdateId(se.Id, mse) } -func mgoAddScheduleEvent(se *models.ScheduleEvent) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SECOL) + +func (m *mongoDB) addScheduleEvent(se *models.ScheduleEvent) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SECOL) count, err := col.Find(bson.M{NAME: se.Name}).Count() if err != nil { return err @@ -58,43 +93,47 @@ func mgoAddScheduleEvent(se *models.ScheduleEvent) error { // Handle DBRefs mse := MongoScheduleEvent{ScheduleEvent: *se} - if err := col.Insert(mse); err != nil { - return err - } - return nil + return col.Insert(mse) } -func mgoGetAllScheduleEvents(se *[]models.ScheduleEvent) error { - return mgoGetScheduleEvents(se, bson.M{}) + +func (m *mongoDB) getAllScheduleEvents(se *[]models.ScheduleEvent) error { + return m.getScheduleEvents(se, bson.M{}) } -func mgoGetScheduleEventByName(se *models.ScheduleEvent, n string) error { - return mgoGetScheduleEvent(se, bson.M{NAME: n}) + +func (m *mongoDB) getScheduleEventByName(se *models.ScheduleEvent, n string) error { + return m.getScheduleEvent(se, bson.M{NAME: n}) } -func mgoGetScheduleEventById(se *models.ScheduleEvent, id string) error { + +func (m *mongoDB) getScheduleEventById(se *models.ScheduleEvent, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetScheduleEvent(se, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getScheduleEvent(se, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetScheduleEventById Invalid Object ID " + id) return err } } -func mgoGetScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error { - return mgoGetScheduleEvents(se, bson.M{SCHEDULE: n}) + +func (m *mongoDB) getScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error { + return m.getScheduleEvents(se, bson.M{SCHEDULE: n}) } -func mgoGetScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error { + +func (m *mongoDB) getScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetScheduleEvents(se, bson.M{ADDRESSABLE + ".$id": bson.ObjectIdHex(id)}) + return m.getScheduleEvents(se, bson.M{ADDRESSABLE + ".$id": bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetScheduleEventsByAddressableId Invalid Object ID" + id) return err } } -func mgoGetScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error { - return mgoGetScheduleEvents(se, bson.M{SERVICE: n}) + +func (m *mongoDB) getScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error { + return m.getScheduleEvents(se, bson.M{SERVICE: n}) } -func mgoGetScheduleEvent(se *models.ScheduleEvent, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SECOL) + +func (m *mongoDB) getScheduleEvent(se *models.ScheduleEvent, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SECOL) // Handle DBRef var mse MongoScheduleEvent @@ -108,10 +147,11 @@ func mgoGetScheduleEvent(se *models.ScheduleEvent, q bson.M) error { return err } -func mgoGetScheduleEvents(se *[]models.ScheduleEvent, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SECOL) + +func (m *mongoDB) getScheduleEvents(se *[]models.ScheduleEvent, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SECOL) // Handle the DBRef var mses []MongoScheduleEvent @@ -128,26 +168,33 @@ func mgoGetScheduleEvents(se *[]models.ScheduleEvent, q bson.M) error { return nil } -/* --------------------------Schedule ---------------------------*/ -func mgoGetAllSchedules(s *[]models.Schedule) error { - return mgoGetSchedules(s, bson.M{}) +func (m *mongoDB) deleteScheduleEvent(se models.ScheduleEvent) error { + return m.deleteById(SECOL, se.Id.Hex()) +} + +// --------------------------Schedule ---------------------------*/ +func (m *mongoDB) getAllSchedules(s *[]models.Schedule) error { + return m.getSchedules(s, bson.M{}) } -func mgoGetScheduleByName(s *models.Schedule, n string) error { - return mgoGetSchedule(s, bson.M{NAME: n}) + +func (m *mongoDB) getScheduleByName(s *models.Schedule, n string) error { + return m.getSchedule(s, bson.M{NAME: n}) } -func mgoGetScheduleById(s *models.Schedule, id string) error { + +func (m *mongoDB) getScheduleById(s *models.Schedule, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetSchedule(s, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getSchedule(s, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetScheduleById Invalid Object ID " + id) return err } } -func mgoAddSchedule(s *models.Schedule) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SCOL) - count, err := col.Find(bson.M{NAME: s.Name}).Count() + +func (m *mongoDB) addSchedule(sch *models.Schedule) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SCOL) + count, err := col.Find(bson.M{NAME: sch.Name}).Count() if err != nil { return err } else if count > 0 { @@ -156,97 +203,88 @@ func mgoAddSchedule(s *models.Schedule) error { } ts := makeTimestamp() - s.Created = ts - s.Modified = ts - s.Id = bson.NewObjectId() - if err := col.Insert(s); err != nil { - return err - } - return nil + sch.Created = ts + sch.Modified = ts + sch.Id = bson.NewObjectId() + return col.Insert(s) } -func mgoUpdateSchedule(s models.Schedule) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SCOL) - s.Modified = makeTimestamp() +func (m *mongoDB) updateSchedule(sch models.Schedule) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SCOL) + + sch.Modified = makeTimestamp() - if err := col.UpdateId(s.Id, s); err != nil { + if err := col.UpdateId(sch.Id, sch); err != nil { return err } return nil } -func mgoGetSchedule(s *models.Schedule, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SCOL) - err := col.Find(q).One(s) - if err != nil { - return err - } - return nil +func (m *mongoDB) deleteSchedule(s models.Schedule) error { + return m.deleteById(SCOL, s.Id.Hex()) } -func mgoGetSchedules(s *[]models.Schedule, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(SCOL) - err := col.Find(q).Sort(QUERYTS).All(s) - if err != nil { - return err - } - return nil +func (m *mongoDB) getSchedule(sch *models.Schedule, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SCOL) + return col.Find(q).One(sch) +} + +func (m *mongoDB) getSchedules(sch *[]models.Schedule, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(SCOL) + return col.Find(q).Sort(QUERYTS).All(sch) } /* ----------------------Device Report --------------------------*/ -func mgoGetAllDeviceReports(d *[]models.DeviceReport) error { - return mgoGetDeviceReports(d, bson.M{}) +func (m *mongoDB) getAllDeviceReports(d *[]models.DeviceReport) error { + return m.getDeviceReports(d, bson.M{}) } -func mgoGetDeviceReportByName(d *models.DeviceReport, n string) error { - return mgoGetDeviceReport(d, bson.M{NAME: n}) + +func (m *mongoDB) getDeviceReportByName(d *models.DeviceReport, n string) error { + return m.getDeviceReport(d, bson.M{NAME: n}) } -func mgoGetDeviceReportByDeviceName(d *[]models.DeviceReport, n string) error { - return mgoGetDeviceReports(d, bson.M{DEVICE: n}) + +func (m *mongoDB) getDeviceReportByDeviceName(d *[]models.DeviceReport, n string) error { + return m.getDeviceReports(d, bson.M{DEVICE: n}) } -func mgoGetDeviceReportById(d *models.DeviceReport, id string) error { + +func (m *mongoDB) getDeviceReportById(d *models.DeviceReport, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetDeviceReport(d, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getDeviceReport(d, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetDeviceReportById Invalid Object ID " + id) return err } } -func mgoGetDeviceReportsByScheduleEventName(d *[]models.DeviceReport, n string) error { - return mgoGetDeviceReports(d, bson.M{"event": n}) + +func (m *mongoDB) getDeviceReportsByScheduleEventName(d *[]models.DeviceReport, n string) error { + return m.getDeviceReports(d, bson.M{"event": n}) } -func mgoGetDeviceReports(d *[]models.DeviceReport, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DRCOL) - err := col.Find(q).Sort(QUERYTS).All(d) - if err != nil { - return err - } - return nil +func (m *mongoDB) getDeviceReports(d *[]models.DeviceReport, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DRCOL) + return col.Find(q).Sort(QUERYTS).All(d) } -func mgoGetDeviceReport(d *models.DeviceReport, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DRCOL) - err := col.Find(q).One(d) - if err != nil { - return err - } - return nil +func (m *mongoDB) getDeviceReport(d *models.DeviceReport, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DRCOL) + return col.Find(q).One(d) } -func mgoAddDeviceReport(d *models.DeviceReport) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DRCOL) + +func (m *mongoDB) addDeviceReport(d *models.DeviceReport) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DRCOL) count, err := col.Find(bson.M{NAME: d.Name}).Count() if err != nil { return err @@ -256,106 +294,26 @@ func mgoAddDeviceReport(d *models.DeviceReport) error { ts := makeTimestamp() d.Created = ts d.Id = bson.NewObjectId() - if err := col.Insert(d); err != nil { - return err - } - - return nil -} -func mgoUpdateDeviceReport(dr *models.DeviceReport) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DRCOL) - - return col.UpdateId(dr.Id, dr) + return col.Insert(d) } -func mgoUpdateByIdInt(c string, did string, pv2 string, p2 int64) error { - if bson.IsObjectIdHex(did) { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(c) - err := col.UpdateId(bson.ObjectIdHex(did), bson.M{"$set": bson.M{pv2: p2, "modified": makeTimestamp()}}) - if err != nil { - return err - } - return nil - } else { - err := errors.New("mgoUpdateByIdInt Invalid Object ID " + did) - return err - } -} -func mgoUpdateById(c string, did string, pv2 string, p2 string) error { - if bson.IsObjectIdHex(did) { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(c) - err := col.UpdateId(bson.ObjectIdHex(did), bson.M{"$set": bson.M{pv2: p2, "modified": makeTimestamp()}}) - if err != nil { - return err - } - - return nil - } else { - err := errors.New("mgoUpdateById Invalid Object ID " + did) - return err - } -} -func mgoUpdateByNameInt(c string, n string, pv2 string, p2 int64) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(c) - err := col.Update(bson.M{"name": n}, bson.M{"$set": bson.M{pv2: p2, "modified": makeTimestamp()}}) - if err != nil { - return err - } - - return nil -} -func mgoUpdateByName(c string, n string, pv2 string, p2 string) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(c) - err := col.Update(bson.M{"name": n}, bson.M{"$set": bson.M{pv2: p2, "modified": makeTimestamp()}}) - if err != nil { - return err - } - - return nil -} -func mgoDeleteById(c string, did string) error { - if bson.IsObjectIdHex(did) { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(c) - err := col.RemoveId(bson.ObjectIdHex(did)) - if err != nil { - return err - } +func (m *mongoDB) updateDeviceReport(dr *models.DeviceReport) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DRCOL) - return nil - } else { - err := errors.New("mgoDeleteById Invalid Object ID " + did) - return err - } + return col.UpdateId(dr.Id, dr) } -func mgoDeleteByName(c string, n string) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(c) - err := col.Remove(bson.M{NAME: n}) - if err != nil { - return err - } - return nil +func (m *mongoDB) deleteDeviceReport(dr models.DeviceReport) error { + return m.deleteById(DRCOL, dr.Id.Hex()) } /* ----------------------------- Device ---------------------------------- */ -func mgoAddNewDevice(d *models.Device) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DEVICECOL) +func (m *mongoDB) addDevice(d *models.Device) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DEVICECOL) // Check if the name exist (Device names must be unique) count, err := col.Find(bson.M{NAME: d.Name}).Count() @@ -373,82 +331,81 @@ func mgoAddNewDevice(d *models.Device) error { // Wrap the device in MongoDevice (For DBRefs) md := MongoDevice{Device: *d} - err = col.Insert(md) - if err != nil { - return err - } - - return nil + return col.Insert(md) } -func mgoUpdateDevice(rd models.Device) error { - ds := DS.dataStore() - defer ds.s.Close() - c := ds.s.DB(DB).C(DEVICECOL) + +func (m *mongoDB) updateDevice(rd models.Device) error { + s := m.s.Copy() + defer s.Close() + c := s.DB(DB).C(DEVICECOL) // Copy over the DBRefs md := MongoDevice{Device: rd} return c.UpdateId(rd.Id, md) } -func mgoGetAllDevices(d *[]models.Device) error { - return mgoGetDevices(d, nil) + +func (m *mongoDB) deleteDevice(d models.Device) error { + return m.deleteById(DEVICECOL, d.Id.Hex()) +} + +func (m *mongoDB) getAllDevices(d *[]models.Device) error { + return m.getDevices(d, nil) } -func mgoGetDevicesByProfileId(d *[]models.Device, pid string) error { + +func (m *mongoDB) getDevicesByProfileId(d *[]models.Device, pid string) error { if bson.IsObjectIdHex(pid) { - return mgoGetDevices(d, bson.M{PROFILE + "." + "$id": bson.ObjectIdHex(pid)}) + return m.getDevices(d, bson.M{PROFILE + "." + "$id": bson.ObjectIdHex(pid)}) } else { err := errors.New("mgoGetDevicesByProfileId Invalid Object ID " + pid) return err } } -func mgoGetDeviceById(d *models.Device, id string) error { + +func (m *mongoDB) getDeviceById(d *models.Device, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetDevice(d, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getDevice(d, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetDeviceById Invalid Object ID " + id) return err } } -func mgoGetDeviceByName(d *models.Device, n string) error { - return mgoGetDevice(d, bson.M{NAME: n}) -} -func mgoGetDevicesByProfileName(d *[]models.Device, pn string) error { - return mgoGetDevices(d, bson.M{PROFILE + "." + NAME: pn}) + +func (m *mongoDB) getDeviceByName(d *models.Device, n string) error { + return m.getDevice(d, bson.M{NAME: n}) } -func mgoGetDevicesByServiceId(d *[]models.Device, sid string) error { + +func (m *mongoDB) getDevicesByServiceId(d *[]models.Device, sid string) error { if bson.IsObjectIdHex(sid) { - return mgoGetDevices(d, bson.M{SERVICE + "." + "$id": bson.ObjectIdHex(sid)}) + return m.getDevices(d, bson.M{SERVICE + "." + "$id": bson.ObjectIdHex(sid)}) } else { err := errors.New("mgoGetDevicesByServiceId Invalid Object ID " + sid) return err } } -func mgoGetDevicesByServiceName(d *[]models.Device, sn string) error { - return mgoGetDevices(d, bson.M{SERVICE + "." + NAME: sn}) -} -func mgoGetDevicesByAddressableId(d *[]models.Device, aid string) error { + +func (m *mongoDB) getDevicesByAddressableId(d *[]models.Device, aid string) error { if bson.IsObjectIdHex(aid) { // Check if the addressable exists var a *models.Addressable - if mgoGetAddressableById(a, aid) == mgo.ErrNotFound { + if m.getAddressableById(a, aid) == mgo.ErrNotFound { return mgo.ErrNotFound } - return mgoGetDevices(d, bson.M{ADDRESSABLE + "." + "$id": bson.ObjectIdHex(aid)}) + return m.getDevices(d, bson.M{ADDRESSABLE + "." + "$id": bson.ObjectIdHex(aid)}) } else { err := errors.New("mgoGetDevicesByAddressableId Invalid Object ID " + aid) return err } } -func mgoGetDevicesByAddressableName(d *[]models.Device, an string) error { - return mgoGetDevices(d, bson.M{ADDRESSABLE + "." + NAME: an}) -} -func mgoGetDevicesWithLabel(d *[]models.Device, l []string) error { - return mgoGetDevices(d, bson.M{LABELS: bson.M{"$in": l}}) + +func (m *mongoDB) getDevicesWithLabel(d *[]models.Device, l []string) error { + return m.getDevices(d, bson.M{LABELS: bson.M{"$in": l}}) } -func mgoGetDevices(d *[]models.Device, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DEVICECOL) + +func (m *mongoDB) getDevices(d *[]models.Device, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DEVICECOL) mds := []MongoDevice{} err := col.Find(q).Sort(QUERYTS).All(&mds) @@ -462,10 +419,11 @@ func mgoGetDevices(d *[]models.Device, q bson.M) error { return nil } -func mgoGetDevice(d *models.Device, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DEVICECOL) + +func (m *mongoDB) getDevice(d *models.Device, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DEVICECOL) md := MongoDevice{} err := col.Find(q).One(&md) @@ -478,76 +436,42 @@ func mgoGetDevice(d *models.Device, q bson.M) error { return nil } -// Query for the aux and de-reference the DBRefs -func query(colStr string, q bson.M, aux interface{}, model interface{}) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(colStr) - - err := col.Find(q).One(aux) - if err != nil { - return err - } - - // Copy over fields and de-reference the references - refAux := reflect.ValueOf(aux).Elem() - refModel := reflect.ValueOf(model).Elem() - for i := 0; i < refAux.NumField(); i++ { - // Get the fields for Aux and Real - name := refAux.Type().Field(i).Name - fAux := refAux.FieldByName(name) - fReal := refModel.FieldByName(name) - - // DBRef type - dereference - if fAux.Type() == reflect.TypeOf(mgo.DBRef{}) { - var aux2 interface{} - model2 := reflect.Zero(reflect.TypeOf(fReal.Interface())).Interface() - - // Make a recursive call to de-reference - query(fAux.Interface().(mgo.DBRef).Collection, bson.M{"_id": fAux.Interface().(mgo.DBRef).Id}, &aux2, &model2) - - // Set the returned value into the Real field - fReal.Set(reflect.ValueOf(model2)) - continue - } - - // Not a DBRef, just copy over the field - fReal.Set(refAux.FieldByName(name)) - } - - return nil -} - /* -----------------------------Device Profile -----------------------------*/ -func mgoGetDeviceProfileById(d *models.DeviceProfile, id string) error { +func (m *mongoDB) getDeviceProfileById(d *models.DeviceProfile, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetDeviceProfile(d, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getDeviceProfile(d, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetDeviceProfileById Invalid Object ID " + id) return err } } -func mgoGetDeviceProfilesByModel(dp *[]models.DeviceProfile, m string) error { - return mgoGetDeviceProfiles(dp, bson.M{MODEL: m}) + +func (m *mongoDB) getAllDeviceProfiles(dp *[]models.DeviceProfile) error { + return m.getDeviceProfiles(dp, nil) +} + +func (m *mongoDB) getDeviceProfilesByModel(dp *[]models.DeviceProfile, model string) error { + return m.getDeviceProfiles(dp, bson.M{MODEL: model}) } -func mgoGetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error { - return mgoGetDeviceProfiles(dp, bson.M{LABELS: bson.M{"$in": l}}) + +func (m *mongoDB) getDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error { + return m.getDeviceProfiles(dp, bson.M{LABELS: bson.M{"$in": l}}) } -func mgoGetDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error { - return mgoGetDeviceProfiles(dp, bson.M{MANUFACTURER: man, MODEL: mod}) +func (m *mongoDB) getDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error { + return m.getDeviceProfiles(dp, bson.M{MANUFACTURER: man, MODEL: mod}) } -func mgoGetDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error { - return mgoGetDeviceProfiles(dp, bson.M{MANUFACTURER: man}) +func (m *mongoDB) getDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error { + return m.getDeviceProfiles(dp, bson.M{MANUFACTURER: man}) } -func mgoGetDeviceProfileByName(dp *models.DeviceProfile, n string) error { - return mgoGetDeviceProfile(dp, bson.M{NAME: n}) +func (m *mongoDB) getDeviceProfileByName(dp *models.DeviceProfile, n string) error { + return m.getDeviceProfile(dp, bson.M{NAME: n}) } // Get device profiles with the passed query -func mgoGetDeviceProfiles(d *[]models.DeviceProfile, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DPCOL) +func (m *mongoDB) getDeviceProfiles(d *[]models.DeviceProfile, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DPCOL) // Handle the DBRefs var mdps []MongoDeviceProfile @@ -564,10 +488,10 @@ func mgoGetDeviceProfiles(d *[]models.DeviceProfile, q bson.M) error { } // Get device profile with the passed query -func mgoGetDeviceProfile(d *models.DeviceProfile, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DPCOL) +func (m *mongoDB) getDeviceProfile(d *models.DeviceProfile, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DPCOL) // Handle the DBRefs var mdp MongoDeviceProfile @@ -580,10 +504,11 @@ func mgoGetDeviceProfile(d *models.DeviceProfile, q bson.M) error { return err } -func mgoAddNewDeviceProfile(dp *models.DeviceProfile) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DPCOL) + +func (m *mongoDB) addDeviceProfile(dp *models.DeviceProfile) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DPCOL) count, err := col.Find(bson.M{NAME: dp.Name}).Count() if err != nil { return err @@ -591,7 +516,7 @@ func mgoAddNewDeviceProfile(dp *models.DeviceProfile) error { return ErrDuplicateName } for i := 0; i < len(dp.Commands); i++ { - if err := addCommand(&dp.Commands[i]); err != nil { + if err := m.addCommand(&dp.Commands[i]); err != nil { return err } } @@ -602,40 +527,36 @@ func mgoAddNewDeviceProfile(dp *models.DeviceProfile) error { mdp := MongoDeviceProfile{DeviceProfile: *dp} - err = col.Insert(mdp) - if err != nil { - return err - } - - return nil + return col.Insert(mdp) } -func mgoUpdateDeviceProfile(dp *models.DeviceProfile) error { - ds := DS.dataStore() - defer ds.s.Close() - c := ds.s.DB(DB).C(DPCOL) + +func (m *mongoDB) updateDeviceProfile(dp *models.DeviceProfile) error { + s := m.s.Copy() + defer s.Close() + c := s.DB(DB).C(DPCOL) mdp := MongoDeviceProfile{DeviceProfile: *dp} mdp.Modified = makeTimestamp() - if err := c.UpdateId(mdp.Id, mdp); err != nil { - return err - } - - return nil + return c.UpdateId(mdp.Id, mdp) } // Get the device profiles that are currently using the command -func mgoGetDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error { +func (m *mongoDB) getDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error { query := bson.M{"commands": bson.M{"$elemMatch": bson.M{"$id": c.Id}}} - return mgoGetDeviceProfiles(dp, query) + return m.getDeviceProfiles(dp, query) +} + +func (m *mongoDB) deleteDeviceProfile(dp models.DeviceProfile) error { + return m.deleteById(DPCOL, dp.Id.Hex()) } -/* -----------------------------------Addressable --------------------------*/ -func mgoUpdateAddressable(ra *models.Addressable, r *models.Addressable) error { - ds := DS.dataStore() +// -----------------------------------Addressable --------------------------*/ +func (m *mongoDB) updateAddressable(ra *models.Addressable, r *models.Addressable) error { + s := m.s.Copy() - defer ds.s.Close() - c := ds.s.DB(DB).C(ADDCOL) + defer s.Close() + c := s.DB(DB).C(ADDCOL) if ra == nil { return nil } @@ -671,10 +592,15 @@ func mgoUpdateAddressable(ra *models.Addressable, r *models.Addressable) error { } return nil } -func mgoGetAddressables(d *[]models.Addressable, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(ADDCOL) + +func (m *mongoDB) getAddressables(d *[]models.Addressable) error { + return m.getAddressablesQuery(d, bson.M{}) +} + +func (m *mongoDB) getAddressablesQuery(d *[]models.Addressable, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(ADDCOL) err := col.Find(q).Sort(QUERYTS).All(d) if err != nil { return err @@ -682,18 +608,20 @@ func mgoGetAddressables(d *[]models.Addressable, q bson.M) error { return nil } -func mgoGetAddressableById(a *models.Addressable, id string) error { + +func (m *mongoDB) getAddressableById(a *models.Addressable, id string) error { if bson.IsObjectIdHex(id) { - return getAddressable(a, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getAddressable(a, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetAddressableById Invalid Object ID " + id) return err } } -func mgoAddNewAddressable(a *models.Addressable) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(ADDCOL) + +func (m *mongoDB) addAddressable(a *models.Addressable) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(ADDCOL) // check if the name exist count, err := col.Find(bson.M{NAME: a.Name}).Count() @@ -713,25 +641,31 @@ func mgoAddNewAddressable(a *models.Addressable) error { return nil } -func mgoGetAddressableByName(a *models.Addressable, n string) error { - return mgoGetAddressable(a, bson.M{NAME: n}) + +func (m *mongoDB) getAddressableByName(a *models.Addressable, n string) error { + return m.getAddressable(a, bson.M{NAME: n}) } -func mgoGetAddressablesByTopic(a *[]models.Addressable, t string) error { - return mgoGetAddressables(a, bson.M{TOPIC: t}) + +func (m *mongoDB) getAddressablesByTopic(a *[]models.Addressable, t string) error { + return m.getAddressablesQuery(a, bson.M{TOPIC: t}) } -func mgoGetAddressablesByPort(a *[]models.Addressable, p int) error { - return mgoGetAddressables(a, bson.M{PORT: p}) + +func (m *mongoDB) getAddressablesByPort(a *[]models.Addressable, p int) error { + return m.getAddressablesQuery(a, bson.M{PORT: p}) } -func mgoGetAddressablesByPublisher(a *[]models.Addressable, p string) error { - return mgoGetAddressables(a, bson.M{PUBLISHER: p}) + +func (m *mongoDB) getAddressablesByPublisher(a *[]models.Addressable, p string) error { + return m.getAddressablesQuery(a, bson.M{PUBLISHER: p}) } -func mgoGetAddressablesByAddress(a *[]models.Addressable, add string) error { - return mgoGetAddressables(a, bson.M{ADDRESS: add}) + +func (m *mongoDB) getAddressablesByAddress(a *[]models.Addressable, add string) error { + return m.getAddressablesQuery(a, bson.M{ADDRESS: add}) } -func mgoGetAddressable(d *models.Addressable, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(ADDCOL) + +func (m *mongoDB) getAddressable(d *models.Addressable, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(ADDCOL) err := col.Find(q).One(d) if err != nil { return err @@ -739,72 +673,46 @@ func mgoGetAddressable(d *models.Addressable, q bson.M) error { return nil } -func mgoIsAddressableAssociatedToDevice(a models.Addressable) (bool, error) { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DEVICECOL) - query := bson.M{ADDRESSABLE + ".$id": a.Id} - count, err := col.Find(query).Count() - if err != nil { - return false, err - } - if count > 0 { - return true, nil - } else { - return false, nil - } -} -func mgoIsAddressableAssociatedToDeviceService(a models.Addressable) (bool, error) { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DSCOL) - query := bson.M{ADDRESSABLE + ".$id": a.Id} - count, err := col.Find(query).Count() - if err != nil { - return false, err - } - - if count > 0 { - return true, nil - } else { - return false, nil - } +func (m *mongoDB) deleteAddressable(a models.Addressable) error { + return m.deleteById(ADDCOL, a.Id.Hex()) } /* ----------------------------- Device Service ----------------------------------*/ -func mgoGetDeviceServiceByName(d *models.DeviceService, n string) error { - return mgoGetDeviceService(d, bson.M{NAME: n}) +func (m *mongoDB) getDeviceServiceByName(d *models.DeviceService, n string) error { + return m.getDeviceService(d, bson.M{NAME: n}) } -func mgoGetDeviceServiceById(d *models.DeviceService, id string) error { + +func (m *mongoDB) getDeviceServiceById(d *models.DeviceService, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetDeviceService(d, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getDeviceService(d, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetDeviceServiceByName Invalid Object ID " + id) return err } } -func mgoGetAllDeviceServices(d *[]models.DeviceService) error { - return mgoGetDeviceServices(d, bson.M{}) -} -func mgoGetDeviceServicesByAddressableName(d *[]models.DeviceService, an string) error { - return mgoGetDeviceServices(d, bson.M{ADDRESSABLE + "." + NAME: an}) + +func (m *mongoDB) getAllDeviceServices(d *[]models.DeviceService) error { + return m.getDeviceServices(d, bson.M{}) } -func mgoGetDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error { + +func (m *mongoDB) getDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetDeviceServices(d, bson.M{ADDRESSABLE + ".$id": bson.ObjectIdHex(id)}) + return m.getDeviceServices(d, bson.M{ADDRESSABLE + ".$id": bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetDeviceServicesByAddressableId Invalid Object ID " + id) return err } } -func mgoGetDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error { - return mgoGetDeviceServices(d, bson.M{LABELS: bson.M{"$in": l}}) + +func (m *mongoDB) getDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error { + return m.getDeviceServices(d, bson.M{LABELS: bson.M{"$in": l}}) } -func mgoGetDeviceServices(d *[]models.DeviceService, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DSCOL) + +func (m *mongoDB) getDeviceServices(d *[]models.DeviceService, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DSCOL) mdss := []MongoDeviceService{} err := col.Find(q).Sort(QUERYTS).All(&mdss) if err != nil { @@ -816,10 +724,11 @@ func mgoGetDeviceServices(d *[]models.DeviceService, q bson.M) error { return nil } -func mgoGetDeviceService(d *models.DeviceService, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DSCOL) + +func (m *mongoDB) getDeviceService(d *models.DeviceService, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DSCOL) mds := MongoDeviceService{} err := col.Find(q).One(&mds) if err != nil { @@ -829,10 +738,11 @@ func mgoGetDeviceService(d *models.DeviceService, q bson.M) error { return nil } -func mgoAddNewDeviceService(d *models.DeviceService) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(DSCOL) + +func (m *mongoDB) addDeviceService(d *models.DeviceService) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(DSCOL) // check if the name exist count, err := col.Find(bson.M{NAME: d.Service.Name}).Count() @@ -849,17 +759,13 @@ func mgoAddNewDeviceService(d *models.DeviceService) error { // MongoDeviceService handles the DBRefs mds := MongoDeviceService{DeviceService: *d} - err = col.Insert(mds) - if err != nil { - return err - } - - return nil + return col.Insert(mds) } -func mgoUpdateDeviceService(deviceService models.DeviceService) error { - ds := DS.dataStore() - defer ds.s.Close() - c := ds.s.DB(DB).C(DSCOL) + +func (m *mongoDB) updateDeviceService(deviceService models.DeviceService) error { + s := m.s.Copy() + defer s.Close() + c := s.DB(DB).C(DSCOL) deviceService.Service.Modified = makeTimestamp() @@ -869,51 +775,53 @@ func mgoUpdateDeviceService(deviceService models.DeviceService) error { return c.UpdateId(deviceService.Service.Id, mds) } -/* ----------------------Provision Watcher -----------------------------*/ -func mgoGetAllProvisionWatchers(pw *[]models.ProvisionWatcher) error { - return mgoGetProvisionWatchers(pw, bson.M{}) +func (m *mongoDB) deleteDeviceService(ds models.DeviceService) error { + return m.deleteById(DSCOL, ds.Id.Hex()) } -func mgoGetProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error { - return mgoGetProvisionWatcher(pw, bson.M{NAME: n}) + +// ----------------------Provision Watcher -----------------------------*/ +func (m *mongoDB) getAllProvisionWatchers(pw *[]models.ProvisionWatcher) error { + return m.getProvisionWatchers(pw, bson.M{}) } -func mgoGetProvisionWatchersByProfileName(pw *[]models.ProvisionWatcher, n string) error { - return mgoGetProvisionWatchers(pw, bson.M{PROFILE + "." + NAME: n}) + +func (m *mongoDB) getProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error { + return m.getProvisionWatcher(pw, bson.M{NAME: n}) } -func mgoGetProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error { - return mgoGetProvisionWatchers(pw, bson.M{IDENTIFIERS + "." + k: v}) + +func (m *mongoDB) getProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error { + return m.getProvisionWatchers(pw, bson.M{IDENTIFIERS + "." + k: v}) } -func mgoGetProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error { + +func (m *mongoDB) getProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetProvisionWatchers(pw, bson.M{SERVICE + ".$id": bson.ObjectIdHex(id)}) + return m.getProvisionWatchers(pw, bson.M{SERVICE + ".$id": bson.ObjectIdHex(id)}) } else { - err := errors.New("mgoGetProvisionWatchersByServiceId Invalid Object ID " + id) - return err + return errors.New("mgoGetProvisionWatchersByServiceId Invalid Object ID " + id) } } -func mgoGetProvisionWatchersByServiceName(pw *[]models.ProvisionWatcher, n string) error { - return mgoGetProvisionWatchers(pw, bson.M{SERVICE + "." + NAME: n}) -} -func mgoGetProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error { +func (m *mongoDB) getProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetProvisionWatchers(pw, bson.M{PROFILE + ".$id": bson.ObjectIdHex(id)}) + return m.getProvisionWatchers(pw, bson.M{PROFILE + ".$id": bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetProvisionWatcherByProfileId Invalid Object ID " + id) return err } } -func mgoGetProvisionWatcherById(pw *models.ProvisionWatcher, id string) error { + +func (m *mongoDB) getProvisionWatcherById(pw *models.ProvisionWatcher, id string) error { if bson.IsObjectIdHex(id) { - return mgoGetProvisionWatcher(pw, bson.M{_ID: bson.ObjectIdHex(id)}) + return m.getProvisionWatcher(pw, bson.M{_ID: bson.ObjectIdHex(id)}) } else { err := errors.New("mgoGetProvisionWatcherById Invalid Object ID " + id) return err } } -func mgoGetProvisionWatcher(pw *models.ProvisionWatcher, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(PWCOL) + +func (m *mongoDB) getProvisionWatcher(pw *models.ProvisionWatcher, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(PWCOL) // Handle DBRefs var mpw MongoProvisionWatcher @@ -927,10 +835,11 @@ func mgoGetProvisionWatcher(pw *models.ProvisionWatcher, q bson.M) error { return err } -func mgoGetProvisionWatchers(pw *[]models.ProvisionWatcher, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(PWCOL) + +func (m *mongoDB) getProvisionWatchers(pw *[]models.ProvisionWatcher, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(PWCOL) // Handle DBRefs var mpws []MongoProvisionWatcher @@ -946,10 +855,11 @@ func mgoGetProvisionWatchers(pw *[]models.ProvisionWatcher, q bson.M) error { return nil } -func mgoAddProvisionWatcher(pw *models.ProvisionWatcher) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(PWCOL) + +func (m *mongoDB) addProvisionWatcher(pw *models.ProvisionWatcher) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(PWCOL) count, err := col.Find(bson.M{NAME: pw.Name}).Count() if err != nil { return err @@ -960,9 +870,9 @@ func mgoAddProvisionWatcher(pw *models.ProvisionWatcher) error { // get Device Service var dev models.DeviceService if pw.Service.Service.Id.Hex() != "" { - mgoGetDeviceServiceById(&dev, pw.Service.Service.Id.Hex()) + m.getDeviceServiceById(&dev, pw.Service.Service.Id.Hex()) } else if pw.Service.Service.Name != "" { - mgoGetDeviceServiceByName(&dev, pw.Service.Service.Name) + m.getDeviceServiceByName(&dev, pw.Service.Service.Name) } else { return errors.New("Device Service ID or Name is required") } @@ -971,9 +881,9 @@ func mgoAddProvisionWatcher(pw *models.ProvisionWatcher) error { // get Device Profile var dp models.DeviceProfile if pw.Profile.Id.Hex() != "" { - mgoGetDeviceProfileById(&dp, pw.Profile.Id.Hex()) + m.getDeviceProfileById(&dp, pw.Profile.Id.Hex()) } else if pw.Profile.Name != "" { - mgoGetDeviceProfileByName(&dp, pw.Profile.Name) + m.getDeviceProfileByName(&dp, pw.Profile.Name) } else { return errors.New("Device Profile ID or Name is required") } @@ -988,16 +898,13 @@ func mgoAddProvisionWatcher(pw *models.ProvisionWatcher) error { // Handle DBRefs mpw := MongoProvisionWatcher{ProvisionWatcher: *pw} - if err := col.Insert(mpw); err != nil { - return err - } - - return nil + return col.Insert(mpw) } -func mgoUpdateProvisionWatcher(pw models.ProvisionWatcher) error { - ds := DS.dataStore() - defer ds.s.Close() - c := ds.s.DB(DB).C(PWCOL) + +func (m *mongoDB) updateProvisionWatcher(pw models.ProvisionWatcher) error { + s := m.s.Copy() + defer s.Close() + c := s.DB(DB).C(PWCOL) pw.Modified = makeTimestamp() @@ -1007,74 +914,63 @@ func mgoUpdateProvisionWatcher(pw models.ProvisionWatcher) error { return c.UpdateId(mpw.Id, mpw) } -/* ------------------------Command -------------------------------------*/ -func mgoGetAllCommands(d *[]models.Command) error { - return mgoGetCommands(d, bson.M{}) +func (m *mongoDB) deleteProvisionWatcher(pw models.ProvisionWatcher) error { + return m.deleteById(PWCOL, pw.Id.Hex()) } -func mgoGetCommands(d *[]models.Command, q bson.M) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(COMCOL) - err := col.Find(q).Sort(QUERYTS).All(d) - if err != nil { - return err - } - return nil +// ------------------------Command -------------------------------------*/ +func (m *mongoDB) getAllCommands(d *[]models.Command) error { + return m.getCommands(d, bson.M{}) } -func mgoGetCommandById(d *models.Command, id string) error { - if bson.IsObjectIdHex(id) { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(COMCOL) - if err := col.Find(bson.M{_ID: bson.ObjectIdHex(id)}).One(d); err != nil { - return err - } - return nil +func (m *mongoDB) getCommands(d *[]models.Command, q bson.M) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(COMCOL) + return col.Find(q).Sort(QUERYTS).All(d) +} + +func (m *mongoDB) getCommandById(d *models.Command, id string) error { + if bson.IsObjectIdHex(id) { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(COMCOL) + return col.Find(bson.M{_ID: bson.ObjectIdHex(id)}).One(d) } else { - err := errors.New("mgoGetCommandById Invalid Object ID " + id) - return err + return errors.New("mgoGetCommandById Invalid Object ID " + id) } } -func mgoGetCommandByName(c *[]models.Command, n string) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(COMCOL) - if err := col.Find(bson.M{NAME: n}).All(c); err != nil { - return err - } - return nil +func (m *mongoDB) getCommandByName(c *[]models.Command, n string) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(COMCOL) + return col.Find(bson.M{NAME: n}).All(c) } -func mgoAddCommand(c *models.Command) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(COMCOL) + +func (m *mongoDB) addCommand(c *models.Command) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(COMCOL) ts := makeTimestamp() c.Created = ts c.Id = bson.NewObjectId() - if err := col.Insert(c); err != nil { - return err - } - - return nil + return col.Insert(c) } // Update command uses the ID of the command for identification -func mgoUpdateCommand(c *models.Command, r *models.Command) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(COMCOL) +func (m *mongoDB) updateCommand(c *models.Command, r *models.Command) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(COMCOL) if c == nil { return nil } // Check if the command has a valid ID if len(c.Id.Hex()) == 0 || !bson.IsObjectIdHex(c.Id.Hex()) { - err := errors.New("ID required for updating a command") - return err + return errors.New("ID required for updating a command") } // Update the fields @@ -1093,18 +989,15 @@ func mgoUpdateCommand(c *models.Command, r *models.Command) error { r.Origin = c.Origin } - if err := col.UpdateId(r.Id, r); err != nil { - return err - } - return nil + return col.UpdateId(r.Id, r) } // Delete the command by ID // Check if the command is still in use by device profiles -func mgoDeleteCommandById(id string) error { - ds := DS.dataStore() - defer ds.s.Close() - col := ds.s.DB(DB).C(COMCOL) +func (m *mongoDB) deleteCommandById(id string) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(COMCOL) if !bson.IsObjectIdHex(id) { return errors.New("Invalid ID") @@ -1112,7 +1005,7 @@ func mgoDeleteCommandById(id string) error { // Check if the command is still in use query := bson.M{"commands": bson.M{"$elemMatch": bson.M{"_id": bson.ObjectIdHex(id)}}} - count, err := ds.s.DB(DB).C(DPCOL).Find(query).Count() + count, err := s.DB(DB).C(DPCOL).Find(query).Count() if err != nil { return err } @@ -1122,3 +1015,32 @@ func mgoDeleteCommandById(id string) error { return col.RemoveId(bson.ObjectIdHex(id)) } + +func (m *mongoDB) deleteById(c string, did string) error { + if bson.IsObjectIdHex(did) { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(c) + err := col.RemoveId(bson.ObjectIdHex(did)) + if err != nil { + return err + } + + return nil + } else { + err := errors.New("Invalid object ID " + did) + return err + } +} + +func (m *mongoDB) deleteByName(c string, n string) error { + s := m.s.Copy() + defer s.Close() + col := s.DB(DB).C(c) + err := col.Remove(bson.M{NAME: n}) + if err != nil { + return err + } + + return nil +} diff --git a/core/metadata/mongo_device.go b/core/metadata/mongo_device.go index 0bb70e8116..60b911eaf4 100644 --- a/core/metadata/mongo_device.go +++ b/core/metadata/mongo_device.go @@ -93,12 +93,13 @@ func (md *MongoDevice) SetBSON(raw bson.Raw) error { md.Location = decoded.Location // De-reference the DBRef fields - ds := DS.dataStore() - defer ds.s.Close() - addCol := ds.s.DB(DB).C(ADDCOL) - dsCol := ds.s.DB(DB).C(DSCOL) - dpCol := ds.s.DB(DB).C(DPCOL) + s := getMongoSessionCopy() + defer s.Close() + + addCol := s.DB(DB).C(ADDCOL) + dsCol := s.DB(DB).C(DSCOL) + dpCol := s.DB(DB).C(DPCOL) var a models.Addressable var mdp MongoDeviceProfile diff --git a/core/metadata/mongo_deviceprofile.go b/core/metadata/mongo_deviceprofile.go index 6f720a0523..0b500fb65a 100644 --- a/core/metadata/mongo_deviceprofile.go +++ b/core/metadata/mongo_deviceprofile.go @@ -104,9 +104,9 @@ func (mdp *MongoDeviceProfile) SetBSON(raw bson.Raw) error { mdp.Resources = decoded.Resources // De-reference the DBRef fields - ds := DS.dataStore() - defer ds.s.Close() - comCol := ds.s.DB(DB).C(COMCOL) + s := getMongoSessionCopy() + defer s.Close() + comCol := s.DB(DB).C(COMCOL) var commands []models.Command diff --git a/core/metadata/mongo_deviceservice.go b/core/metadata/mongo_deviceservice.go index 3c19d98033..0bc81a248e 100644 --- a/core/metadata/mongo_deviceservice.go +++ b/core/metadata/mongo_deviceservice.go @@ -80,10 +80,10 @@ func (mds *MongoDeviceService) SetBSON(raw bson.Raw) error { mds.Service.Labels = decoded.Labels // De-reference the DBRef fields - ds := DS.dataStore() - defer ds.s.Close() + s := getMongoSessionCopy() + defer s.Close() - addCol := ds.s.DB(DB).C(ADDCOL) + addCol := s.DB(DB).C(ADDCOL) var a models.Addressable diff --git a/core/metadata/mongo_provisionwatcher.go b/core/metadata/mongo_provisionwatcher.go index c52415dab8..c80431d715 100644 --- a/core/metadata/mongo_provisionwatcher.go +++ b/core/metadata/mongo_provisionwatcher.go @@ -71,11 +71,11 @@ func (mpw *MongoProvisionWatcher) SetBSON(raw bson.Raw) error { mpw.OperatingState = decoded.OperatingState // De-reference the DBRef fields - ds := DS.dataStore() - defer ds.s.Close() + s := getMongoSessionCopy() + defer s.Close() - profCol := ds.s.DB(DB).C(DPCOL) - servCol := ds.s.DB(DB).C(DSCOL) + profCol := s.DB(DB).C(DPCOL) + servCol := s.DB(DB).C(DSCOL) var mdp MongoDeviceProfile var mds MongoDeviceService diff --git a/core/metadata/mongo_scheduleevent.go b/core/metadata/mongo_scheduleevent.go index 00e8e745cf..09fd310fc2 100644 --- a/core/metadata/mongo_scheduleevent.go +++ b/core/metadata/mongo_scheduleevent.go @@ -72,10 +72,10 @@ func (mse *MongoScheduleEvent) SetBSON(raw bson.Raw) error { mse.Service = decoded.Service // De-reference the DBRef fields - ds := DS.dataStore() - defer ds.s.Close() + s := getMongoSessionCopy() + defer s.Close() - addCol := ds.s.DB(DB).C(ADDCOL) + addCol := s.DB(DB).C(ADDCOL) var a models.Addressable diff --git a/core/metadata/rest_addressable.go b/core/metadata/rest_addressable.go index 7a3da44451..f7524f4a5f 100644 --- a/core/metadata/rest_addressable.go +++ b/core/metadata/rest_addressable.go @@ -23,12 +23,11 @@ import ( "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" - "gopkg.in/mgo.v2/bson" ) func restGetAllAddressables(w http.ResponseWriter, _ *http.Request) { results := make([]models.Addressable, 0) - err := getAddressables(&results, bson.M{}) + err := db.getAddressables(&results) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -63,7 +62,7 @@ func restAddAddressable(w http.ResponseWriter, r *http.Request) { } } - err = addAddressable(&a) + err = db.addAddressable(&a) if err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate name for addressable", http.StatusConflict) @@ -94,10 +93,10 @@ func restUpdateAddressable(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var res models.Addressable - err := getAddressableById(&res, ra.Id.Hex()) + err := db.getAddressableById(&res, ra.Id.Hex()) if err != nil { if ra.Id == "" { - err = getAddressableByName(&res, ra.Name) + err = db.getAddressableByName(&res, ra.Name) } if err != nil { if err == mgo.ErrNotFound { @@ -126,7 +125,7 @@ func restUpdateAddressable(w http.ResponseWriter, r *http.Request) { } } - if err := updateAddressable(&ra, &res); err != nil { + if err := db.updateAddressable(&ra, &res); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -142,11 +141,12 @@ func restUpdateAddressable(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("true")) } + func restGetAddressableById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var id string = vars["id"] var result models.Addressable - if err := getAddressableById(&result, id); err != nil { + if err := db.getAddressableById(&result, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -164,7 +164,7 @@ func restDeleteAddressableById(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err := getAddressableById(&a, id) + err := db.getAddressableById(&a, id) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -185,7 +185,7 @@ func restDeleteAddressableById(w http.ResponseWriter, r *http.Request) { return } - err = deleteById(ADDCOL, id) + err = db.deleteAddressable(a) if err != nil { if err == mgo.ErrNotFound { loggingClient.Error(err.Error(), "") @@ -214,7 +214,7 @@ func restDeleteAddressableByName(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err = getAddressableByName(&a, n) + err = db.getAddressableByName(&a, n) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -235,7 +235,7 @@ func restDeleteAddressableByName(w http.ResponseWriter, r *http.Request) { return } - if err := deleteByName(ADDCOL, n); err != nil { + if err := db.deleteAddressable(a); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -256,7 +256,7 @@ func restDeleteAddressableByName(w http.ResponseWriter, r *http.Request) { func isAddressableStillInUse(a models.Addressable) (bool, error) { // Check devices var d []models.Device - err := getDevicesByAddressableId(&d, a.Id.Hex()) + err := db.getDevicesByAddressableId(&d, a.Id.Hex()) if err != nil { return false, err } @@ -266,7 +266,7 @@ func isAddressableStillInUse(a models.Addressable) (bool, error) { // Check device services var ds []models.DeviceService - err = getDeviceServicesByAddressableId(&ds, a.Id.Hex()) + err = db.getDeviceServicesByAddressableId(&ds, a.Id.Hex()) if err != nil { return false, err } @@ -285,7 +285,7 @@ func restGetAddressableByName(w http.ResponseWriter, r *http.Request) { return } var result models.Addressable - if err := getAddressableByName(&result, dn); err != nil { + if err := db.getAddressableByName(&result, dn); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -309,7 +309,7 @@ func restGetAddressableByTopic(w http.ResponseWriter, r *http.Request) { } res := make([]models.Addressable, 0) - err = getAddressablesByTopic(&res, t) + err = db.getAddressablesByTopic(&res, t) if err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { @@ -334,7 +334,7 @@ func restGetAddressableByPort(w http.ResponseWriter, r *http.Request) { } res := make([]models.Addressable, 0) - if err := getAddressablesByPort(&res, p); err != nil { + if err := db.getAddressablesByPort(&res, p); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -352,7 +352,7 @@ func restGetAddressableByPublisher(w http.ResponseWriter, r *http.Request) { return } res := make([]models.Addressable, 0) - err = getAddressablesByPublisher(&res, p) + err = db.getAddressablesByPublisher(&res, p) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -371,7 +371,7 @@ func restGetAddressableByAddress(w http.ResponseWriter, r *http.Request) { return } res := make([]models.Addressable, 0) - err = getAddressablesByAddress(&res, a) + err = db.getAddressablesByAddress(&res, a) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -385,7 +385,7 @@ func restGetAddressableByAddress(w http.ResponseWriter, r *http.Request) { // Notify the associated device services for the addressable func notifyAddressableAssociates(a models.Addressable, action string) error { var ds []models.DeviceService - if err := getDeviceServicesByAddressableId(&ds, a.Id.Hex()); err != nil { + if err := db.getDeviceServicesByAddressableId(&ds, a.Id.Hex()); err != nil { loggingClient.Error(err.Error(), "") return err } diff --git a/core/metadata/rest_command.go b/core/metadata/rest_command.go index ed00d415bd..31e2ac3cd0 100644 --- a/core/metadata/rest_command.go +++ b/core/metadata/rest_command.go @@ -26,7 +26,7 @@ import ( func restGetAllCommands(w http.ResponseWriter, _ *http.Request) { results := make([]models.Command, 0) - err := getAllCommands(&results) + err := db.getAllCommands(&results) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusInternalServerError) @@ -52,7 +52,7 @@ func restAddCommand(w http.ResponseWriter, r *http.Request) { return } - if err := addCommand(&c); err != nil { + if err := db.addCommand(&c); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -76,7 +76,7 @@ func restUpdateCommand(w http.ResponseWriter, r *http.Request) { } // Check if command exists (By ID) - err := getCommandById(&res, c.Id.Hex()) + err := db.getCommandById(&res, c.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -86,7 +86,7 @@ func restUpdateCommand(w http.ResponseWriter, r *http.Request) { // Name is changed, make sure the new name doesn't conflict with device profile if c.Name != "" { var dp []models.DeviceProfile - err = getDeviceProfilesUsingCommand(&dp, c) + err = db.getDeviceProfilesUsingCommand(&dp, c) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -106,7 +106,7 @@ func restUpdateCommand(w http.ResponseWriter, r *http.Request) { } } - if err := updateCommand(&c, &res); err != nil { + if err := db.updateCommand(&c, &res); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -120,7 +120,7 @@ func restGetCommandById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.Command - err := getCommandById(&res, did) + err := db.getCommandById(&res, did) if err != nil { if err == ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -144,7 +144,7 @@ func restGetCommandByName(w http.ResponseWriter, r *http.Request) { return } results := []models.Command{} - err = getCommandByName(&results, n) + err = db.getCommandByName(&results, n) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -162,7 +162,7 @@ func restDeleteCommandById(w http.ResponseWriter, r *http.Request) { // Check if the command exists var c models.Command - err := getCommandById(&c, id) + err := db.getCommandById(&c, id) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -183,7 +183,7 @@ func restDeleteCommandById(w http.ResponseWriter, r *http.Request) { return } - if err := deleteCommandById(id); err != nil { + if err := db.deleteCommandById(id); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -202,7 +202,7 @@ func restDeleteCommandById(w http.ResponseWriter, r *http.Request) { // Helper function to determine if the command is still in use by device profiles func isCommandStillInUse(c models.Command) (bool, error) { var dp []models.DeviceProfile - err := getDeviceProfilesUsingCommand(&dp, c) + err := db.getDeviceProfilesUsingCommand(&dp, c) if err != nil { return false, err } diff --git a/core/metadata/rest_device.go b/core/metadata/rest_device.go index 03e3fafcb3..6559b911f6 100644 --- a/core/metadata/rest_device.go +++ b/core/metadata/rest_device.go @@ -20,18 +20,18 @@ import ( "net/url" "strconv" "time" + "fmt" "github.com/edgexfoundry/edgex-go/core/domain/models" notifications "github.com/edgexfoundry/edgex-go/support/notifications-client" "github.com/gorilla/mux" "gopkg.in/mgo.v2" - "fmt" "gopkg.in/mgo.v2/bson" ) func restGetAllDevices(w http.ResponseWriter, _ *http.Request) { res := make([]models.Device, 0) - err := getAllDevices(&res) + err := db.getAllDevices(&res) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -67,10 +67,10 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { // Addressable check // Try by name - err = getAddressableByName(&d.Addressable, d.Addressable.Name) + err = db.getAddressableByName(&d.Addressable, d.Addressable.Name) if err != nil { // Try by ID - err = getAddressableById(&d.Addressable, d.Addressable.Id.Hex()) + err = db.getAddressableById(&d.Addressable, d.Addressable.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error()+": A device must be associated to an Addressable", http.StatusConflict) @@ -80,10 +80,10 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { // Service Check // Try by name - err = getDeviceServiceByName(&d.Service, d.Service.Service.Name) + err = db.getDeviceServiceByName(&d.Service, d.Service.Service.Name) if err != nil { // Try by ID - err = getDeviceServiceById(&d.Service, d.Service.Service.Id.Hex()) + err = db.getDeviceServiceById(&d.Service, d.Service.Service.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error()+": A device must be associated with a device service", http.StatusConflict) @@ -93,10 +93,10 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { // Profile Check // Try by name - err = getDeviceProfileByName(&d.Profile, d.Profile.Name) + err = db.getDeviceProfileByName(&d.Profile, d.Profile.Name) if err != nil { // Try by ID - err = getDeviceProfileById(&d.Profile, d.Profile.Id.Hex()) + err = db.getDeviceProfileById(&d.Profile, d.Profile.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error()+": A device must be associated with a device profile", http.StatusConflict) @@ -113,7 +113,7 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { } // Add the device - err = addDevice(&d) + err = db.addDevice(&d) if err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate name for device", http.StatusConflict) @@ -147,10 +147,10 @@ func restUpdateDevice(w http.ResponseWriter, r *http.Request) { // Check if the device exists var oldDevice models.Device // First try ID - err = getDeviceById(&oldDevice, rd.Id.Hex()) + err = db.getDeviceById(&oldDevice, rd.Id.Hex()) if err != nil { // Then try name - err = getDeviceByName(&oldDevice, rd.Name) + err = db.getDeviceByName(&oldDevice, rd.Name) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -164,7 +164,7 @@ func restUpdateDevice(w http.ResponseWriter, r *http.Request) { return } - if err = UpdateDevice(oldDevice); err != nil { + if err = db.updateDevice(oldDevice); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -183,10 +183,10 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the new addressable exists var a models.Addressable // Try ID first - err := getAddressableById(&a, from.Addressable.Id.Hex()) + err := db.getAddressableById(&a, from.Addressable.Id.Hex()) if err != nil { // Then try name - err = getAddressableByName(&a, from.Addressable.Name) + err = db.getAddressableByName(&a, from.Addressable.Name) if err != nil { return errors.New("Addressable not found for updated device") } @@ -198,10 +198,10 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the new service exists var ds models.DeviceService // Try ID first - err := getDeviceServiceById(&ds, from.Service.Service.Id.Hex()) + err := db.getDeviceServiceById(&ds, from.Service.Service.Id.Hex()) if err != nil { // Then try name - err = getDeviceServiceByName(&ds, from.Service.Service.Name) + err = db.getDeviceServiceByName(&ds, from.Service.Service.Name) if err != nil { return errors.New("Device service not found for updated device") } @@ -213,10 +213,10 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the new profile exists var dp models.DeviceProfile // Try ID first - err := getDeviceProfileById(&dp, from.Profile.Id.Hex()) + err := db.getDeviceProfileById(&dp, from.Profile.Id.Hex()) if err != nil { // Then try Name - err = getDeviceProfileByName(&dp, from.Profile.Name) + err = db.getDeviceProfileByName(&dp, from.Profile.Name) if err != nil { return errors.New("Device profile not found for updated device") } @@ -253,7 +253,7 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the name is unique var checkD models.Device - err := getDeviceByName(&checkD, from.Name) + err := db.getDeviceByName(&checkD, from.Name) if err != nil { // A problem occured accessing database if err != mgo.ErrNotFound { @@ -289,7 +289,7 @@ func restGetDevicesWithLabel(w http.ResponseWriter, r *http.Request) { labels = append(labels, label) res := make([]models.Device, 0) - err = getDevicesWithLabel(&res, labels) + err = db.getDevicesWithLabel(&res, labels) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -306,7 +306,7 @@ func restGetDeviceByProfileId(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - err := getDeviceProfileById(&dp, pid) + err := db.getDeviceProfileById(&dp, pid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -318,7 +318,7 @@ func restGetDeviceByProfileId(w http.ResponseWriter, r *http.Request) { } res := make([]models.Device, 0) - err = getDevicesByProfileId(&res, pid) + err = db.getDevicesByProfileId(&res, pid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -336,7 +336,7 @@ func restGetDeviceByServiceId(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - err := getDeviceServiceById(&ds, sid) + err := db.getDeviceServiceById(&ds, sid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -347,7 +347,7 @@ func restGetDeviceByServiceId(w http.ResponseWriter, r *http.Request) { return } - err = getDevicesByServiceId(&res, sid) + err = db.getDevicesByServiceId(&res, sid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -370,7 +370,7 @@ func restGetDeviceByServiceName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - err = getDeviceServiceByName(&ds, sn) + err = db.getDeviceServiceByName(&ds, sn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -384,7 +384,7 @@ func restGetDeviceByServiceName(w http.ResponseWriter, r *http.Request) { res := make([]models.Device, 0) // Find devices by service ID now that you have the Service object (and therefor the ID) - err = getDevicesByServiceId(&res, ds.Service.Id.Hex()) + err = db.getDevicesByServiceId(&res, ds.Service.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -406,7 +406,7 @@ func restGetDeviceByAddressableName(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err = getAddressableByName(&a, an) + err = db.getAddressableByName(&a, an) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -420,7 +420,7 @@ func restGetDeviceByAddressableName(w http.ResponseWriter, r *http.Request) { res := make([]models.Device, 0) // Use the addressable ID now that you have the addressable object - err = getDevicesByAddressableId(&res, a.Id.Hex()) + err = db.getDevicesByAddressableId(&res, a.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -442,7 +442,7 @@ func restGetDeviceByProfileName(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - err = getDeviceProfileByName(&dp, pn) + err = db.getDeviceProfileByName(&dp, pn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -456,7 +456,7 @@ func restGetDeviceByProfileName(w http.ResponseWriter, r *http.Request) { res := make([]models.Device, 0) // Use profile ID now that you have the profile object - err = getDevicesByProfileId(&res, dp.Id.Hex()) + err = db.getDevicesByProfileId(&res, dp.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -473,7 +473,7 @@ func restGetDeviceByAddressableId(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err := getAddressableById(&a, aid) + err := db.getAddressableById(&a, aid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -485,7 +485,7 @@ func restGetDeviceByAddressableId(w http.ResponseWriter, r *http.Request) { } res := make([]models.Device, 0) - err = getDevicesByAddressableId(&res, aid) + err = db.getDevicesByAddressableId(&res, aid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -500,7 +500,7 @@ func restGetDeviceById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.Device - if err := getDeviceById(&res, did); err != nil { + if err := db.getDeviceById(&res, did); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -519,19 +519,19 @@ func restCheckForDevice(w http.ResponseWriter, r *http.Request) { token := vars[ID] //referring to this as "token" for now since the source variable is double purposed dev := models.Device{} //Check for name first since we're using that meaning by default. - if err := getDeviceByName(&dev, token); err != nil { + if err := db.getDeviceByName(&dev, token); err != nil { if err != mgo.ErrNotFound { loggingClient.Error(err.Error(), "restCheckForDevice") http.Error(w, err.Error(), http.StatusInternalServerError) return } else { - loggingClient.Debug(fmt.Sprintf("device %s %v", token, err),"restCheckForDevice") + loggingClient.Debug(fmt.Sprintf("device %s %v", token, err), "restCheckForDevice") } } //If lookup by name failed, see if we were passed the ID if len(dev.Name) == 0 { if bson.IsObjectIdHex(token) { - if err := getDeviceById(&dev, token); err != nil { + if err := db.getDeviceById(&dev, token); err != nil { loggingClient.Error(err.Error(), "restCheckForDevice") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -541,7 +541,7 @@ func restCheckForDevice(w http.ResponseWriter, r *http.Request) { return } } else { - http.Error(w, "device not found: " + token, http.StatusNotFound) + http.Error(w, "device not found: "+token, http.StatusNotFound) return } } @@ -554,7 +554,7 @@ func restSetDeviceOpStateById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] // TODO check if DID needs to be a bson var os string = vars[OPSTATE] - f := models.IsOperatingStateType(os) + newOs, f := models.GetOperatingState(os) if !f { err := errors.New("Invalid State: " + os + " Must be 'ENABLED' or 'DISABLED'") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -564,7 +564,7 @@ func restSetDeviceOpStateById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err := getDeviceById(&d, did) + err := db.getDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -576,7 +576,8 @@ func restSetDeviceOpStateById(w http.ResponseWriter, r *http.Request) { } // Update OpState - if err = setOpState(d, os, w); err != nil { + d.OperatingState = newOs + if err = db.updateDevice(d); err != nil { return } if err != nil { @@ -585,6 +586,9 @@ func restSetDeviceOpStateById(w http.ResponseWriter, r *http.Request) { return } + // Notify + notifyDeviceAssociates(d, http.MethodPut) + w.WriteHeader(http.StatusOK) w.Write([]byte("true")) return @@ -599,7 +603,7 @@ func restSetDeviceOpStateByName(w http.ResponseWriter, r *http.Request) { return } var os string = vars[OPSTATE] - f := models.IsOperatingStateType(os) + newOs, f := models.GetOperatingState(os) // Opstate is invalid if !f { err := errors.New("Invalid State: " + os + " Must be 'ENABLED' or 'DISABLED'") @@ -610,7 +614,7 @@ func restSetDeviceOpStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -622,34 +626,25 @@ func restSetDeviceOpStateByName(w http.ResponseWriter, r *http.Request) { } // Update OpState - if err = setOpState(d, os, w); err != nil { - return - } - - w.WriteHeader(http.StatusOK) - w.Write([]byte("true")) -} - -// Update the opstate of the device -func setOpState(d models.Device, os string, w http.ResponseWriter) error { - err := setById(DEVICECOL, d.Id.Hex(), "operatingState", os) - if err != nil { + d.OperatingState = newOs + if err = db.updateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) - return err + return } // Notify notifyDeviceAssociates(d, http.MethodPut) - return nil + w.WriteHeader(http.StatusOK) + w.Write([]byte("true")) } func restSetDeviceAdminStateById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var as string = vars[ADMINSTATE] - f := models.IsAdminStateType(as) + newAs, f := models.GetAdminState(as) if !f { err := errors.New("Invalid State: " + as + " Must be 'LOCKED' or 'UNLOCKED'") loggingClient.Error(err.Error(), "") @@ -659,7 +654,7 @@ func restSetDeviceAdminStateById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err := getDeviceById(&d, did) + err := db.getDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -671,7 +666,16 @@ func restSetDeviceAdminStateById(w http.ResponseWriter, r *http.Request) { } // Update the AdminState - if err = setAdminState(d, as, w); err != nil { + d.AdminState = newAs + if err = db.updateDevice(d); err != nil { + loggingClient.Error(err.Error(), "") + http.Error(w, err.Error(), http.StatusServiceUnavailable) + return + } + + if err := notifyDeviceAssociates(d, http.MethodPut); err != nil { + loggingClient.Error(err.Error(), "") + http.Error(w, err.Error(), http.StatusServiceUnavailable) return } @@ -690,7 +694,7 @@ func restSetDeviceAdminStateByName(w http.ResponseWriter, r *http.Request) { } var as string = vars[ADMINSTATE] - f := models.IsAdminStateType(as) + newAs, f := models.GetAdminState(as) if !f { err = errors.New("Invalid State: " + as + " Must be 'LOCKED' or 'UNLOCKED'") loggingClient.Error(err.Error(), "") @@ -700,7 +704,7 @@ func restSetDeviceAdminStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -711,29 +715,23 @@ func restSetDeviceAdminStateByName(w http.ResponseWriter, r *http.Request) { return } + d.AdminState = newAs // Update the admin state - if err = setAdminState(d, as, w); err != nil { - return - } - - w.WriteHeader(http.StatusOK) - w.Write([]byte("true")) - return -} - -// Update the admin state for the device -func setAdminState(d models.Device, as string, w http.ResponseWriter) error { - if err := setById(DEVICECOL, d.Id.Hex(), ADMINSTATE, as); err != nil { + if err = db.updateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) - return err + return } if err := notifyDeviceAssociates(d, http.MethodPut); err != nil { - return err + loggingClient.Error(err.Error(), "") + http.Error(w, err.Error(), http.StatusServiceUnavailable) + return } - return nil + w.WriteHeader(http.StatusOK) + w.Write([]byte("true")) + return } func restDeleteDeviceById(w http.ResponseWriter, r *http.Request) { @@ -743,7 +741,7 @@ func restDeleteDeviceById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device //err := getDeviceById(&d, did) - if err := getDeviceById(&d, did); err != nil { + if err := db.getDeviceById(&d, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -772,7 +770,7 @@ func restDeleteDeviceByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -791,16 +789,18 @@ func restDeleteDeviceByName(w http.ResponseWriter, r *http.Request) { // Delete the device func deleteDevice(d models.Device, w http.ResponseWriter) error { if err := deleteAssociatedReportsForDevice(d, w); err != nil { + http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } - if err := deleteById(DEVICECOL, d.Id.Hex()); err != nil { + if err := db.deleteDevice(d); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } // Notify Associates if err := notifyDeviceAssociates(d, http.MethodDelete); err != nil { + http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -810,7 +810,7 @@ func deleteDevice(d models.Device, w http.ResponseWriter) error { // Delete the associated device reports for the device func deleteAssociatedReportsForDevice(d models.Device, w http.ResponseWriter) error { var reports []models.DeviceReport - if err := getDeviceReportByDeviceName(&reports, d.Name); err != nil { + if err := db.getDeviceReportByDeviceName(&reports, d.Name); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return err @@ -818,7 +818,7 @@ func deleteAssociatedReportsForDevice(d models.Device, w http.ResponseWriter) er // Delete the associated reports for _, report := range reports { - if err := deleteById(DRCOL, report.Id.Hex()); err != nil { + if err := db.deleteDeviceReport(report); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return err @@ -842,7 +842,7 @@ func restSetDeviceLastConnectedById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceById(&d, did) + err = db.getDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -882,7 +882,7 @@ func restSetLastConnectedByIdNotify(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceById(&d, did) + err = db.getDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -920,7 +920,7 @@ func restSetDeviceLastConnectedByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -964,7 +964,7 @@ func restSetDeviceLastConnectedByNameNotify(w http.ResponseWriter, r *http.Reque // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -986,7 +986,8 @@ func restSetDeviceLastConnectedByNameNotify(w http.ResponseWriter, r *http.Reque // Update the last connected value for the device func setLastConnected(d models.Device, time int64, notify bool, w http.ResponseWriter) error { - if err := setByIdInt(DEVICECOL, d.Id.Hex(), LASTCONNECTED, time); err != nil { + d.LastConnected = time + if err := db.updateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return err @@ -1012,7 +1013,7 @@ func restSetDeviceLastReportedById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceById(&d, did) + err = db.getDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1051,7 +1052,7 @@ func restSetDeviceLastReportedByIdNotify(w http.ResponseWriter, r *http.Request) // Check if the device exists var d models.Device - err = getDeviceById(&d, did) + err = db.getDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1089,7 +1090,7 @@ func restSetDeviceLastReportedByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1133,7 +1134,7 @@ func restSetDeviceLastReportedByNameNotify(w http.ResponseWriter, r *http.Reques // Check if the device exists var d models.Device - err = getDeviceByName(&d, n) + err = db.getDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1155,7 +1156,8 @@ func restSetDeviceLastReportedByNameNotify(w http.ResponseWriter, r *http.Reques // Update the last reported field of the device func setLastReported(d models.Device, time int64, notify bool, w http.ResponseWriter) error { - if err := setByIdInt(DEVICECOL, d.Id.Hex(), LASTREPORTED, time); err != nil { + d.LastReported = time + if err := db.updateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return err @@ -1177,7 +1179,7 @@ func restGetDeviceByName(w http.ResponseWriter, r *http.Request) { return } var res models.Device - err = getDeviceByName(&res, dn) + err = db.getDeviceByName(&res, dn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1198,7 +1200,7 @@ func notifyDeviceAssociates(d models.Device, action string) error { // Callback for device service var ds models.DeviceService - if err := getDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { + if err := db.getDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { loggingClient.Error(err.Error(), "") return err } diff --git a/core/metadata/rest_deviceprofile.go b/core/metadata/rest_deviceprofile.go index 2063ec3f62..5fc5493c9a 100644 --- a/core/metadata/rest_deviceprofile.go +++ b/core/metadata/rest_deviceprofile.go @@ -28,7 +28,7 @@ import ( func restGetAllDeviceProfiles(w http.ResponseWriter, _ *http.Request) { res := []models.DeviceProfile{} - if err := getAllDeviceProfiles(&res); err != nil { + if err := db.getAllDeviceProfiles(&res); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -70,7 +70,7 @@ func restAddDeviceProfile(w http.ResponseWriter, r *http.Request) { } } - if err := addDeviceProfile(&dp); err != nil { + if err := db.addDeviceProfile(&dp); err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate name for device profile", http.StatusConflict) } else { @@ -97,10 +97,10 @@ func restUpdateDeviceProfile(w http.ResponseWriter, r *http.Request) { // Check if the Device Profile exists var to models.DeviceProfile // First try with ID - err := getDeviceProfileById(&to, from.Id.Hex()) + err := db.getDeviceProfileById(&to, from.Id.Hex()) if err != nil { // Try with name - err = getDeviceProfileByName(&to, from.Name) + err = db.getDeviceProfileByName(&to, from.Name) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -113,7 +113,7 @@ func restUpdateDeviceProfile(w http.ResponseWriter, r *http.Request) { loggingClient.Error(err.Error(), "") return } - if err := updateDeviceProfile(&to); err != nil { + if err := db.updateDeviceProfile(&to); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -187,7 +187,7 @@ func updateDeviceProfileFields(from models.DeviceProfile, to *models.DeviceProfi // Check for duplicate names in device profiles func checkDuplicateProfileNames(dp models.DeviceProfile, w http.ResponseWriter) error { profiles := []models.DeviceProfile{} - if err := getAllDeviceProfiles(&profiles); err != nil { + if err := db.getAllDeviceProfiles(&profiles); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -226,7 +226,7 @@ func checkDuplicateCommands(dp models.DeviceProfile, w http.ResponseWriter) erro // Delete all of the commands that are a part of the device profile func deleteCommands(dp models.DeviceProfile, w http.ResponseWriter) error { for _, command := range dp.Commands { - err := deleteCommandById(command.Id.Hex()) + err := db.deleteCommandById(command.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err @@ -239,7 +239,7 @@ func deleteCommands(dp models.DeviceProfile, w http.ResponseWriter) error { // Add all of the commands that are a part of the device profile func addCommands(dp *models.DeviceProfile, w http.ResponseWriter) error { for i := range dp.Commands { - if err := addCommand(&(dp.Commands[i])); err != nil { + if err := db.addCommand(&(dp.Commands[i])); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -252,7 +252,7 @@ func restGetProfileByProfileId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars["id"] var res models.DeviceProfile - if err := getDeviceProfileById(&res, did); err != nil { + if err := db.getDeviceProfileById(&res, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -271,7 +271,7 @@ func restDeleteProfileByProfileId(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - if err := getDeviceProfileById(&dp, did); err != nil { + if err := db.getDeviceProfileById(&dp, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -303,7 +303,7 @@ func restDeleteProfileByName(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - if err = getDeviceProfileByName(&dp, n); err != nil { + if err = db.getDeviceProfileByName(&dp, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -329,7 +329,7 @@ func restDeleteProfileByName(w http.ResponseWriter, r *http.Request) { func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { // Check if the device profile is still in use by devices var d []models.Device - if err := getDevicesByProfileId(&d, dp.Id.Hex()); err != nil { + if err := db.getDevicesByProfileId(&d, dp.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -341,7 +341,7 @@ func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { // Check if the device profile is still in use by provision watchers var pw []models.ProvisionWatcher - if err := getProvisionWatcherByProfileId(&pw, dp.Id.Hex()); err != nil { + if err := db.getProvisionWatcherByProfileId(&pw, dp.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -352,7 +352,7 @@ func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { } // Delete the profile - if err := deleteDeviceProfileById(dp.Id.Hex()); err != nil { + if err := db.deleteDeviceProfile(dp); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -430,7 +430,7 @@ func addDeviceProfileYaml(data []byte, w http.ResponseWriter) { } } - if err := addDeviceProfile(&dp); err != nil { + if err := db.addDeviceProfile(&dp); err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate profile name", http.StatusConflict) } else { @@ -454,7 +454,7 @@ func restGetProfileByModel(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceProfile, 0) - if err := getDeviceProfilesByModel(&res, an); err != nil { + if err := db.getDeviceProfilesByModel(&res, an); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -476,7 +476,7 @@ func restGetProfileWithLabel(w http.ResponseWriter, r *http.Request) { var labels []string labels = append(labels, label) res := make([]models.DeviceProfile, 0) - if err := getDeviceProfilesWithLabel(&res, labels); err != nil { + if err := db.getDeviceProfilesWithLabel(&res, labels); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -503,7 +503,7 @@ func restGetProfileByManufacturerModel(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceProfile, 0) - if err := getDeviceProfilesByManufacturerModel(&res, man, mod); err != nil { + if err := db.getDeviceProfilesByManufacturerModel(&res, man, mod); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -523,7 +523,7 @@ func restGetProfileByManufacturer(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceProfile, 0) - if err := getDeviceProfilesByManufacturer(&res, man); err != nil { + if err := db.getDeviceProfilesByManufacturer(&res, man); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -544,7 +544,7 @@ func restGetProfileByName(w http.ResponseWriter, r *http.Request) { // Get the device var res models.DeviceProfile - if err := getDeviceProfileByName(&res, dn); err != nil { + if err := db.getDeviceProfileByName(&res, dn); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -569,7 +569,7 @@ func restGetYamlProfileByName(w http.ResponseWriter, r *http.Request) { // Check for the device profile var dp models.DeviceProfile - err = getDeviceProfileByName(&dp, name) + err = db.getDeviceProfileByName(&dp, name) if err != nil { // Not found, return nil if err == mgo.ErrNotFound { @@ -607,7 +607,7 @@ func restGetYamlProfileById(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - err := getDeviceProfileById(&dp, id) + err := db.getDeviceProfileById(&dp, id) if err != nil { if err == mgo.ErrNotFound { w.WriteHeader(http.StatusNotFound) @@ -636,7 +636,7 @@ func restGetYamlProfileById(w http.ResponseWriter, r *http.Request) { func notifyProfileAssociates(dp models.DeviceProfile, action string) error { // Get the devices var d []models.Device - if err := getDevicesByProfileId(&d, dp.Id.Hex()); err != nil { + if err := db.getDevicesByProfileId(&d, dp.Id.Hex()); err != nil { loggingClient.Error(err.Error(), "") return err } diff --git a/core/metadata/rest_devicereport.go b/core/metadata/rest_devicereport.go index 2fcc0913ec..16e33f51f4 100644 --- a/core/metadata/rest_devicereport.go +++ b/core/metadata/rest_devicereport.go @@ -26,7 +26,7 @@ import ( func restGetAllDeviceReports(w http.ResponseWriter, _ *http.Request) { res := make([]models.DeviceReport, 0) - err := getAllDeviceReports(&res) + err := db.getAllDeviceReports(&res) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -59,7 +59,7 @@ func restAddDeviceReport(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - if err := getDeviceByName(&d, dr.Device); err != nil { + if err := db.getDeviceByName(&d, dr.Device); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device referenced by Device Report doesn't exist", http.StatusNotFound) } else { @@ -71,7 +71,7 @@ func restAddDeviceReport(w http.ResponseWriter, r *http.Request) { // Check if the Schedule Event exists var se models.ScheduleEvent - if err := getScheduleEventByName(&se, dr.Event); err != nil { + if err := db.getScheduleEventByName(&se, dr.Event); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule Event referenced by Device Report doesn't exist", http.StatusNotFound) } else { @@ -82,7 +82,7 @@ func restAddDeviceReport(w http.ResponseWriter, r *http.Request) { } // Add the device report - if err := addDeviceReport(&dr); err != nil { + if err := db.addDeviceReport(&dr); err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate Name for the device report", http.StatusConflict) } else { @@ -113,9 +113,9 @@ func restUpdateDeviceReport(w http.ResponseWriter, r *http.Request) { // Check if the device report exists var to models.DeviceReport // First try ID - if err := getDeviceReportById(&to, from.Id.Hex()); err != nil { + if err := db.getDeviceReportById(&to, from.Id.Hex()); err != nil { // Try by name - if err = getDeviceReportByName(&to, from.Name); err != nil { + if err = db.getDeviceReportByName(&to, from.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -131,7 +131,7 @@ func restUpdateDeviceReport(w http.ResponseWriter, r *http.Request) { return } - if err := updateDeviceReport(&to); err != nil { + if err := db.updateDeviceReport(&to); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -177,7 +177,7 @@ func updateDeviceReportFields(from models.DeviceReport, to *models.DeviceReport, // Validate that the device exists func validateDevice(d string, w http.ResponseWriter) error { var device models.Device - if err := getDeviceByName(&device, d); err != nil { + if err := db.getDeviceByName(&device, d); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device was not found", http.StatusNotFound) } else { @@ -192,7 +192,7 @@ func validateDevice(d string, w http.ResponseWriter) error { // Validate that the schedule event exists func validateEvent(e string, w http.ResponseWriter) error { var event models.ScheduleEvent - if err := getScheduleEventByName(&event, e); err != nil { + if err := db.getScheduleEventByName(&event, e); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Event was not found", http.StatusNotFound) } else { @@ -208,7 +208,7 @@ func restGetReportById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.DeviceReport - err := getDeviceReportById(&res, did) + err := db.getDeviceReportById(&res, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -233,7 +233,7 @@ func restGetReportByName(w http.ResponseWriter, r *http.Request) { } var res models.DeviceReport - err = getDeviceReportByName(&res, n) + err = db.getDeviceReportByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -261,7 +261,7 @@ func restGetValueDescriptorsForDeviceName(w http.ResponseWriter, r *http.Request // Get all the associated device reports var reports []models.DeviceReport - if err = getDeviceReportByDeviceName(&reports, n); err != nil { + if err = db.getDeviceReportByDeviceName(&reports, n); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -287,7 +287,7 @@ func restGetDeviceReportByDeviceName(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceReport, 0) - err = getDeviceReportByDeviceName(&res, n) + err = db.getDeviceReportByDeviceName(&res, n) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -304,7 +304,7 @@ func restDeleteReportById(w http.ResponseWriter, r *http.Request) { // Check if the device report exists var dr models.DeviceReport - if err := getDeviceReportById(&dr, id); err != nil { + if err := db.getDeviceReportById(&dr, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -334,7 +334,7 @@ func restDeleteReportByName(w http.ResponseWriter, r *http.Request) { // Check if the device report exists var dr models.DeviceReport - if err = getDeviceReportByName(&dr, n); err != nil { + if err = db.getDeviceReportByName(&dr, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -354,7 +354,7 @@ func restDeleteReportByName(w http.ResponseWriter, r *http.Request) { } func deleteDeviceReport(dr models.DeviceReport, w http.ResponseWriter) error { - if err := deleteById(DRCOL, dr.Id.Hex()); err != nil { + if err := db.deleteDeviceReport(dr); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -371,13 +371,13 @@ func deleteDeviceReport(dr models.DeviceReport, w http.ResponseWriter) error { func notifyDeviceReportAssociates(dr models.DeviceReport, action string) error { // Get the device of the report var d models.Device - if err := getDeviceByName(&d, dr.Device); err != nil { + if err := db.getDeviceByName(&d, dr.Device); err != nil { return err } // Get the device service for the device var ds models.DeviceService - if err := getDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { + if err := db.getDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { return err } diff --git a/core/metadata/rest_deviceservice.go b/core/metadata/rest_deviceservice.go index 73d9610764..60fa3db1e1 100644 --- a/core/metadata/rest_deviceservice.go +++ b/core/metadata/rest_deviceservice.go @@ -33,9 +33,9 @@ func getAddressableByIdOrName(a *models.Addressable, w http.ResponseWriter) erro name := a.Name // Try by ID - if err := getAddressableById(a, id.Hex()); err != nil { + if err := db.getAddressableById(a, id.Hex()); err != nil { // Try by name - if err = getAddressableByName(a, name); err != nil { + if err = db.getAddressableByName(a, name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found", http.StatusServiceUnavailable) } else { @@ -50,7 +50,7 @@ func getAddressableByIdOrName(a *models.Addressable, w http.ResponseWriter) erro func restGetAllDeviceServices(w http.ResponseWriter, _ *http.Request) { r := make([]models.DeviceService, 0) - if err := getAllDeviceServices(&r); err != nil { + if err := db.getAllDeviceServices(&r); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -89,7 +89,7 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { var foundAddressable = false // First try by name - err = getAddressableByName(&ds.Service.Addressable, ds.Service.Addressable.Name) + err = db.getAddressableByName(&ds.Service.Addressable, ds.Service.Addressable.Name) if err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -102,7 +102,7 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { // Then try by ID if !foundAddressable { - err := getAddressableById(&ds.Service.Addressable, ds.Service.Addressable.Id.Hex()) + err := db.getAddressableById(&ds.Service.Addressable, ds.Service.Addressable.Id.Hex()) if err != nil { http.Error(w, "Addressable not found by ID or Name", http.StatusNotFound) loggingClient.Error("Addressable not found by ID or Name: "+err.Error(), "") @@ -114,7 +114,7 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { } // Add the device service - if err := addDeviceService(&ds); err != nil { + if err := db.addDeviceService(&ds); err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate name for the device service", http.StatusConflict) } else { @@ -136,7 +136,7 @@ func restGetAddressablesForAssociatedDevicesById(w http.ResponseWriter, r *http. var ds models.DeviceService // Check if the device service exists - if err := getDeviceServiceById(&ds, id); err != nil { + if err := db.getDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -170,7 +170,7 @@ func restGetAddressablesForAssociatedDevicesByName(w http.ResponseWriter, r *htt // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, n); err != nil { + if err = db.getDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -195,7 +195,7 @@ func restGetAddressablesForAssociatedDevicesByName(w http.ResponseWriter, r *htt func getAddressablesForAssociatedDevices(addressables *[]models.Addressable, ds models.DeviceService, w http.ResponseWriter) error { // Get the associated devices var devices []models.Device - if err := getDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { + if err := db.getDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -228,9 +228,9 @@ func restUpdateDeviceService(w http.ResponseWriter, r *http.Request) { // Check if the device service exists and get it var to models.DeviceService // Try by ID - if err = getDeviceServiceById(&to, from.Service.Id.Hex()); err != nil { + if err = db.getDeviceServiceById(&to, from.Service.Id.Hex()); err != nil { // Try by Name - if err = getDeviceServiceByName(&to, from.Service.Name); err != nil { + if err = db.getDeviceServiceByName(&to, from.Service.Name); err != nil { http.Error(w, "Device service not found", http.StatusNotFound) loggingClient.Error(err.Error(), "") return @@ -242,7 +242,7 @@ func restUpdateDeviceService(w http.ResponseWriter, r *http.Request) { return } - if err := updateDeviceService(to); err != nil { + if err := db.updateDeviceService(to); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -287,7 +287,7 @@ func updateDeviceServiceFields(from models.DeviceService, to *models.DeviceServi // Check if the new name is unique var checkDS models.DeviceService - err := getDeviceServiceByName(&checkDS, from.Service.Name) + err := db.getDeviceServiceByName(&checkDS, from.Service.Name) if err != nil { // A problem occured accessing database if err != mgo.ErrNotFound { @@ -335,7 +335,7 @@ func restGetServiceByAddressableName(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - if err = getAddressableByName(&a, an); err != nil { + if err = db.getAddressableByName(&a, an); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found", http.StatusNotFound) } else { @@ -345,7 +345,7 @@ func restGetServiceByAddressableName(w http.ResponseWriter, r *http.Request) { return } - if err = getDeviceServicesByAddressableId(&res, a.Id.Hex()); err != nil { + if err = db.getDeviceServicesByAddressableId(&res, a.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return @@ -362,7 +362,7 @@ func restGetServiceByAddressableId(w http.ResponseWriter, r *http.Request) { // Check if the Addressable exists var a models.Addressable - if err := getAddressableById(&a, sid); err != nil { + if err := db.getAddressableById(&a, sid); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found", http.StatusNotFound) } else { @@ -372,7 +372,7 @@ func restGetServiceByAddressableId(w http.ResponseWriter, r *http.Request) { return } - if err := getDeviceServicesByAddressableId(&res, sid); err != nil { + if err := db.getDeviceServicesByAddressableId(&res, sid); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -394,7 +394,7 @@ func restGetServiceWithLabel(w http.ResponseWriter, r *http.Request) { ls = append(ls, l) res := make([]models.DeviceService, 0) - if err := getDeviceServicesWithLabel(&res, ls); err != nil { + if err := db.getDeviceServicesWithLabel(&res, ls); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -414,7 +414,7 @@ func restGetServiceByName(w http.ResponseWriter, r *http.Request) { } var res models.DeviceService - err = getDeviceServiceByName(&res, dn) + err = db.getDeviceServiceByName(&res, dn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -435,7 +435,7 @@ func restDeleteServiceById(w http.ResponseWriter, r *http.Request) { // Check if the device service exists and get it var ds models.DeviceService - if err := getDeviceServiceById(&ds, id); err != nil { + if err := db.getDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -464,7 +464,7 @@ func restDeleteServiceByName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, n); err != nil { + if err = db.getDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -490,7 +490,7 @@ func restDeleteServiceByName(w http.ResponseWriter, r *http.Request) { func deleteDeviceService(ds models.DeviceService, w http.ResponseWriter) error { // Delete the associated devices var devices []models.Device - if err := getDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { + if err := db.getDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -502,7 +502,7 @@ func deleteDeviceService(ds models.DeviceService, w http.ResponseWriter) error { // Delete the associated provision watchers var watchers []models.ProvisionWatcher - if err := getProvisionWatchersByServiceId(&watchers, ds.Service.Id.Hex()); err != nil { + if err := db.getProvisionWatchersByServiceId(&watchers, ds.Service.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -513,7 +513,7 @@ func deleteDeviceService(ds models.DeviceService, w http.ResponseWriter) error { } // Delete the device service - if err := deleteById(DSCOL, ds.Service.Id.Hex()); err != nil { + if err := db.deleteDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -534,7 +534,7 @@ func restUpdateServiceLastConnectedById(w http.ResponseWriter, r *http.Request) // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceById(&ds, id); err != nil { + if err = db.getDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -571,7 +571,7 @@ func restUpdateServiceLastConnectedByName(w http.ResponseWriter, r *http.Request // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, n); err != nil { + if err = db.getDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -593,7 +593,9 @@ func restUpdateServiceLastConnectedByName(w http.ResponseWriter, r *http.Request // Update the last connected value of the device service func updateServiceLastConnected(ds models.DeviceService, lc int64, w http.ResponseWriter) error { - if err := setByIdInt(DSCOL, ds.Service.Id.Hex(), LASTCONNECTED, lc); err != nil { + ds.LastConnected = lc + + if err := db.updateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -606,7 +608,7 @@ func restGetServiceById(w http.ResponseWriter, r *http.Request) { var did string = vars[ID] var res models.DeviceService - if err := getDeviceServiceById(&res, did); err != nil { + if err := db.getDeviceServiceById(&res, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -626,7 +628,8 @@ func restUpdateServiceOpStateById(w http.ResponseWriter, r *http.Request) { var os string = vars[OPSTATE] // Check the OpState - if !models.IsOperatingStateType(os) { + newOs, f := models.GetOperatingState(os) + if !f { err := errors.New("Invalid State: " + os + " Must be 'ENABLED' or 'DISABLED'") loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -635,7 +638,7 @@ func restUpdateServiceOpStateById(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err := getDeviceServiceById(&ds, id); err != nil { + if err := db.getDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -645,7 +648,7 @@ func restUpdateServiceOpStateById(w http.ResponseWriter, r *http.Request) { return } - if err := updateServiceOpState(ds, os, w); err != nil { + if err := updateServiceOpState(ds, newOs, w); err != nil { loggingClient.Error(err.Error(), "") return } @@ -665,7 +668,8 @@ func restUpdateServiceOpStateByName(w http.ResponseWriter, r *http.Request) { var os string = vars[OPSTATE] // Check the OpState - if !models.IsOperatingStateType(os) { + newOs, f := models.GetOperatingState(os) + if !f { err = errors.New("Invalid State: " + os + " Must be 'ENABLED' or 'DISABLED'") loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -674,7 +678,7 @@ func restUpdateServiceOpStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, n); err != nil { + if err = db.getDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -684,7 +688,7 @@ func restUpdateServiceOpStateByName(w http.ResponseWriter, r *http.Request) { return } - if err := updateServiceOpState(ds, os, w); err != nil { + if err := updateServiceOpState(ds, newOs, w); err != nil { loggingClient.Error(err.Error(), "") return } @@ -694,8 +698,9 @@ func restUpdateServiceOpStateByName(w http.ResponseWriter, r *http.Request) { } // Update the OpState for the device service -func updateServiceOpState(ds models.DeviceService, os string, w http.ResponseWriter) error { - if err := setById(DSCOL, ds.Service.Id.Hex(), OPERATINGSTATE, os); err != nil { +func updateServiceOpState(ds models.DeviceService, os models.OperatingState, w http.ResponseWriter) error { + ds.OperatingState = os + if err := db.updateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -709,7 +714,8 @@ func restUpdateServiceAdminStateById(w http.ResponseWriter, r *http.Request) { var as string = vars[ADMINSTATE] // Check the admin state - if !models.IsAdminStateType(as) { + newAs, f := models.GetAdminState(as) + if !f { err := errors.New("Invalid state: " + as + " Must be 'LOCKED' or 'UNLOCKED'") http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -718,7 +724,7 @@ func restUpdateServiceAdminStateById(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err := getDeviceServiceById(&ds, id); err != nil { + if err := db.getDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -729,7 +735,7 @@ func restUpdateServiceAdminStateById(w http.ResponseWriter, r *http.Request) { } // Update the admin state - if err := updateServiceAdminState(ds, as, w); err != nil { + if err := updateServiceAdminState(ds, newAs, w); err != nil { loggingClient.Error(err.Error(), "") return } @@ -749,7 +755,8 @@ func restUpdateServiceAdminStateByName(w http.ResponseWriter, r *http.Request) { var as string = vars[ADMINSTATE] // Check the admin state - if !models.IsAdminStateType(as) { + newAs, f := models.GetAdminState(as) + if !f { err := errors.New("Invalid state: " + as + " Must be 'LOCKED' or 'UNLOCKED'") http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -758,7 +765,7 @@ func restUpdateServiceAdminStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, n); err != nil { + if err = db.getDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -769,7 +776,7 @@ func restUpdateServiceAdminStateByName(w http.ResponseWriter, r *http.Request) { } // Update the admins state - if err = updateServiceAdminState(ds, as, w); err != nil { + if err = updateServiceAdminState(ds, newAs, w); err != nil { loggingClient.Error(err.Error(), "") return } @@ -779,8 +786,9 @@ func restUpdateServiceAdminStateByName(w http.ResponseWriter, r *http.Request) { } // Update the admin state for the device service -func updateServiceAdminState(ds models.DeviceService, as string, w http.ResponseWriter) error { - if err := setById(DSCOL, ds.Service.Id.Hex(), ADMINSTATE, as); err != nil { +func updateServiceAdminState(ds models.DeviceService, as models.AdminState, w http.ResponseWriter) error { + ds.AdminState = as + if err := db.updateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -801,7 +809,7 @@ func restUpdateServiceLastReportedById(w http.ResponseWriter, r *http.Request) { // Check if the devicde service exists var ds models.DeviceService - if err = getDeviceServiceById(&ds, id); err != nil { + if err = db.getDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -838,7 +846,7 @@ func restUpdateServiceLastReportedByName(w http.ResponseWriter, r *http.Request) // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, n); err != nil { + if err = db.getDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -859,7 +867,8 @@ func restUpdateServiceLastReportedByName(w http.ResponseWriter, r *http.Request) // Update the last reported value for the device service func updateServiceLastReported(ds models.DeviceService, lr int64, w http.ResponseWriter) error { - if err := setByIdInt(DSCOL, ds.Service.Id.Hex(), LASTREPORTED, lr); err != nil { + ds.LastReported = lr + if err := db.updateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } diff --git a/core/metadata/rest_provisionwatcher.go b/core/metadata/rest_provisionwatcher.go index 7a93c2a38a..9ef1e93541 100644 --- a/core/metadata/rest_provisionwatcher.go +++ b/core/metadata/rest_provisionwatcher.go @@ -26,7 +26,7 @@ import ( func restGetProvisionWatchers(w http.ResponseWriter, _ *http.Request) { res := make([]models.ProvisionWatcher, 0) - if err := getAllProvisionWatchers(&res); err != nil { + if err := db.getAllProvisionWatchers(&res); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return @@ -50,7 +50,7 @@ func restDeleteProvisionWatcherById(w http.ResponseWriter, r *http.Request) { // Check if the provision watcher exists var pw models.ProvisionWatcher - if err := getProvisionWatcherById(&pw, id); err != nil { + if err := db.getProvisionWatcherById(&pw, id); err != nil { errMessage := "Provision Watcher not found by ID: " + err.Error() loggingClient.Error(errMessage, "") http.Error(w, errMessage, http.StatusNotFound) @@ -76,7 +76,7 @@ func restDeleteProvisionWatcherByName(w http.ResponseWriter, r *http.Request) { // Check if the provision watcher exists var pw models.ProvisionWatcher - if err = getProvisionWatcherByName(&pw, n); err != nil { + if err = db.getProvisionWatcherByName(&pw, n); err != nil { if err == mgo.ErrNotFound { errMessage := "Provision watcher not found: " + err.Error() http.Error(w, errMessage, http.StatusNotFound) @@ -99,7 +99,7 @@ func restDeleteProvisionWatcherByName(w http.ResponseWriter, r *http.Request) { // Delete the provision watcher func deleteProvisionWatcher(pw models.ProvisionWatcher, w http.ResponseWriter) error { - if err := deleteById(PWCOL, pw.Id.Hex()); err != nil { + if err := db.deleteProvisionWatcher(pw); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -116,7 +116,7 @@ func restGetProvisionWatcherById(w http.ResponseWriter, r *http.Request) { var id string = vars[ID] var res models.ProvisionWatcher - if err := getProvisionWatcherById(&res, id); err != nil { + if err := db.getProvisionWatcherById(&res, id); err != nil { if err == mgo.ErrNotFound { errMessage := "Problem getting provision watcher by ID: " + err.Error() loggingClient.Error(errMessage, "") @@ -142,7 +142,7 @@ func restGetProvisionWatcherByName(w http.ResponseWriter, r *http.Request) { } var res models.ProvisionWatcher - err = getProvisionWatcherByName(&res, n) + err = db.getProvisionWatcherByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -163,14 +163,14 @@ func restGetProvisionWatchersByProfileId(w http.ResponseWriter, r *http.Request) // Check if the device profile exists var dp models.DeviceProfile - if err := getDeviceProfileById(&dp, pid); err != nil { + if err := db.getDeviceProfileById(&dp, pid); err != nil { loggingClient.Error("Device profile not found: "+err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) return } res := make([]models.ProvisionWatcher, 0) - err := getProvisionWatcherByProfileId(&res, pid) + err := db.getProvisionWatcherByProfileId(&res, pid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -191,7 +191,7 @@ func restGetProvisionWatchersByProfileName(w http.ResponseWriter, r *http.Reques // Check if the device profile exists var dp models.DeviceProfile - if err = getDeviceProfileByName(&dp, pn); err != nil { + if err = db.getDeviceProfileByName(&dp, pn); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device profile not found", http.StatusNotFound) loggingClient.Error("Device profile not found: "+err.Error(), "") @@ -203,7 +203,7 @@ func restGetProvisionWatchersByProfileName(w http.ResponseWriter, r *http.Reques } res := make([]models.ProvisionWatcher, 0) - err = getProvisionWatcherByProfileId(&res, dp.Id.Hex()) + err = db.getProvisionWatcherByProfileId(&res, dp.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -219,14 +219,14 @@ func restGetProvisionWatchersByServiceId(w http.ResponseWriter, r *http.Request) // Check if the device service exists var ds models.DeviceService - if err := getDeviceServiceById(&ds, sid); err != nil { + if err := db.getDeviceServiceById(&ds, sid); err != nil { http.Error(w, "Device Service not found", http.StatusNotFound) loggingClient.Error("Device service not found: "+err.Error(), "") return } res := make([]models.ProvisionWatcher, 0) - err := getProvisionWatchersByServiceId(&res, sid) + err := db.getProvisionWatchersByServiceId(&res, sid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -247,7 +247,7 @@ func restGetProvisionWatchersByServiceName(w http.ResponseWriter, r *http.Reques // Check if the device service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, sn); err != nil { + if err = db.getDeviceServiceByName(&ds, sn); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) loggingClient.Error("Device service not found: "+err.Error(), "") @@ -260,7 +260,7 @@ func restGetProvisionWatchersByServiceName(w http.ResponseWriter, r *http.Reques // Get the provision watchers res := make([]models.ProvisionWatcher, 0) - err = getProvisionWatchersByServiceId(&res, ds.Service.Id.Hex()) + err = db.getProvisionWatchersByServiceId(&res, ds.Service.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -286,7 +286,7 @@ func restGetProvisionWatchersByIdentifier(w http.ResponseWriter, r *http.Request } res := make([]models.ProvisionWatcher, 0) - if err := getProvisionWatchersByIdentifier(&res, k, v); err != nil { + if err := db.getProvisionWatchersByIdentifier(&res, k, v); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watchers: "+err.Error(), "") return @@ -314,9 +314,9 @@ func restAddProvisionWatcher(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists // Try by ID - if err := getDeviceProfileById(&pw.Profile, pw.Profile.Id.Hex()); err != nil { + if err := db.getDeviceProfileById(&pw.Profile, pw.Profile.Id.Hex()); err != nil { // Try by name - if err = getDeviceProfileByName(&pw.Profile, pw.Profile.Name); err != nil { + if err = db.getDeviceProfileByName(&pw.Profile, pw.Profile.Name); err != nil { if err == mgo.ErrNotFound { loggingClient.Error("Device profile not found for provision watcher: "+err.Error(), "") http.Error(w, "Device profile not found for provision watcher", http.StatusConflict) @@ -330,9 +330,9 @@ func restAddProvisionWatcher(w http.ResponseWriter, r *http.Request) { // Check if the device service exists // Try by ID - if err := getDeviceServiceById(&pw.Service, pw.Service.Service.Id.Hex()); err != nil { + if err := db.getDeviceServiceById(&pw.Service, pw.Service.Service.Id.Hex()); err != nil { // Try by name - if err = getDeviceServiceByName(&pw.Service, pw.Service.Service.Name); err != nil { + if err = db.getDeviceServiceByName(&pw.Service, pw.Service.Service.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found for provision watcher", http.StatusConflict) loggingClient.Error("Device service not found for provision watcher: "+err.Error(), "") @@ -344,7 +344,7 @@ func restAddProvisionWatcher(w http.ResponseWriter, r *http.Request) { } } - if err := addProvisionWatcher(&pw); err != nil { + if err := db.addProvisionWatcher(&pw); err != nil { if err == ErrDuplicateName { loggingClient.Error("Duplicate name for the provision watcher: "+err.Error(), "") http.Error(w, "Duplicate name for the provision watcher", http.StatusConflict) @@ -379,9 +379,9 @@ func restUpdateProvisionWatcher(w http.ResponseWriter, r *http.Request) { // Check if the provision watcher exists var to models.ProvisionWatcher // Try by ID - if err := getProvisionWatcherById(&to, from.Id.Hex()); err != nil { + if err := db.getProvisionWatcherById(&to, from.Id.Hex()); err != nil { // Try by name - if err = getProvisionWatcherByName(&to, from.Name); err != nil { + if err = db.getProvisionWatcherByName(&to, from.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Provision watcher not found", http.StatusNotFound) loggingClient.Error("Provision watcher not found: "+err.Error(), "") @@ -398,7 +398,7 @@ func restUpdateProvisionWatcher(w http.ResponseWriter, r *http.Request) { return } - if err := updateProvisionWatcher(to); err != nil { + if err := db.updateProvisionWatcher(to); err != nil { loggingClient.Error("Problem updating provision watcher: "+err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -424,7 +424,7 @@ func updateProvisionWatcherFields(from models.ProvisionWatcher, to *models.Provi if from.Name != "" { // Check that the name is unique var checkPW models.ProvisionWatcher - err := getProvisionWatcherByName(&checkPW, from.Name) + err := db.getProvisionWatcherByName(&checkPW, from.Name) if err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -449,7 +449,7 @@ func updateProvisionWatcherFields(from models.ProvisionWatcher, to *models.Provi func notifyProvisionWatcherAssociates(pw models.ProvisionWatcher, action string) error { // Get the device service for the provision watcher var ds models.DeviceService - if err := getDeviceServiceById(&ds, pw.Service.Service.Id.Hex()); err != nil { + if err := db.getDeviceServiceById(&ds, pw.Service.Service.Id.Hex()); err != nil { return err } diff --git a/core/metadata/rest_scheduleevent.go b/core/metadata/rest_scheduleevent.go index 5b9fd2de47..0c59ce451a 100644 --- a/core/metadata/rest_scheduleevent.go +++ b/core/metadata/rest_scheduleevent.go @@ -47,7 +47,7 @@ func msToTime(ms string) (time.Time, error) { func restGetAllScheduleEvents(w http.ResponseWriter, r *http.Request) { res := make([]models.ScheduleEvent, 0) - err := getAllScheduleEvents(&res) + err := db.getAllScheduleEvents(&res) if err != nil { loggingClient.Error("Problem getting schedule events: "+err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -81,7 +81,7 @@ func restAddScheduleEvent(w http.ResponseWriter, r *http.Request) { return } var s models.Schedule - if err := getScheduleByName(&s, se.Schedule); err != nil { + if err := db.getScheduleByName(&s, se.Schedule); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found for schedule event", http.StatusNotFound) loggingClient.Error("Schedule not found for schedule event: "+err.Error(), "") @@ -95,9 +95,9 @@ func restAddScheduleEvent(w http.ResponseWriter, r *http.Request) { // Check for the addressable // Try by ID var a models.Addressable - if err := getAddressableById(&a, se.Addressable.Id.Hex()); err != nil { + if err := db.getAddressableById(&a, se.Addressable.Id.Hex()); err != nil { // Try by Name - if err = getAddressableByName(&a, se.Addressable.Name); err != nil { + if err = db.getAddressableByName(&a, se.Addressable.Name); err != nil { http.Error(w, "Address not found for schedule event", http.StatusNotFound) loggingClient.Error("Addressable for schedule event not found: "+err.Error(), "") return @@ -133,7 +133,7 @@ func restAddScheduleEvent(w http.ResponseWriter, r *http.Request) { return }*/ - if err := addScheduleEvent(&se); err != nil { + if err := db.addScheduleEvent(&se); err != nil { if err == ErrDuplicateName { http.Error(w, "Duplicate name for schedule event", http.StatusConflict) loggingClient.Error("Duplicate name for schedule event: "+err.Error(), "") @@ -175,7 +175,7 @@ func restUpdateScheduleEvent(w http.ResponseWriter, r *http.Request) { return } - if err := updateScheduleEvent(to); err != nil { + if err := db.updateScheduleEvent(to); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem updating schedule event: "+err.Error(), "") return @@ -194,9 +194,9 @@ func restUpdateScheduleEvent(w http.ResponseWriter, r *http.Request) { func getScheduleEventByIdOrName(from models.ScheduleEvent, w http.ResponseWriter) (models.ScheduleEvent, error) { var se models.ScheduleEvent // Try by ID - if err := getScheduleEventById(&se, from.Id.Hex()); err != nil { + if err := db.getScheduleEventById(&se, from.Id.Hex()); err != nil { // Try by Name - if err = getScheduleEventByName(&se, from.Name); err != nil { + if err = db.getScheduleEventByName(&se, from.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule Event not found", http.StatusNotFound) loggingClient.Error(err.Error(), "") @@ -221,9 +221,9 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve if (from.Addressable.String() != models.Addressable{}.String()) { // Check if the new addressable exists // Try by ID - if err := getAddressableById(&from.Addressable, from.Addressable.Id.Hex()); err != nil { + if err := db.getAddressableById(&from.Addressable, from.Addressable.Id.Hex()); err != nil { // Try by name - if err = getAddressableByName(&from.Addressable, from.Addressable.Name); err != nil { + if err = db.getAddressableByName(&from.Addressable, from.Addressable.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found for schedule event", http.StatusNotFound) } else { @@ -240,7 +240,7 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve serviceChanged = true // Verify that the new service exists var checkDS models.DeviceService - if err := getDeviceServiceByName(&checkDS, from.Service); err != nil { + if err := db.getDeviceServiceByName(&checkDS, from.Service); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device Service not found for schedule event", http.StatusNotFound) } else { @@ -257,7 +257,7 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve if from.Schedule != to.Schedule { // Verify that the new schedule exists var checkS models.Schedule - if err := getScheduleByName(&checkS, from.Schedule); err != nil { + if err := db.getScheduleByName(&checkS, from.Schedule); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found for schedule event", http.StatusNotFound) } else { @@ -273,7 +273,7 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve if from.Name != to.Name { // Verify data integrity var reports []models.DeviceReport - if err := getDeviceReportsByScheduleEventName(&reports, to.Name); err != nil { + if err := db.getDeviceReportsByScheduleEventName(&reports, to.Name); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -320,7 +320,7 @@ func restGetScheduleEventByName(w http.ResponseWriter, r *http.Request) { } var res models.ScheduleEvent - err = getScheduleEventByName(&res, n) + err = db.getScheduleEventByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule event not found", http.StatusNotFound) @@ -342,7 +342,7 @@ func restDeleteScheduleEventById(w http.ResponseWriter, r *http.Request) { // Check if the schedule event exists var se models.ScheduleEvent - err := getScheduleEventById(&se, id) + err := db.getScheduleEventById(&se, id) if err != nil { http.Error(w, "Schedule event not found", http.StatusNotFound) loggingClient.Error("Schedule event not found: "+err.Error(), "") @@ -370,7 +370,7 @@ func restDeleteScheduleEventByName(w http.ResponseWriter, r *http.Request) { // Check if the schedule event exists var se models.ScheduleEvent - if err := getScheduleEventByName(&se, n); err != nil { + if err := db.getScheduleEventByName(&se, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule event not found", http.StatusNotFound) loggingClient.Error("Schedule event not found: "+err.Error(), "") @@ -396,7 +396,7 @@ func restDeleteScheduleEventByName(w http.ResponseWriter, r *http.Request) { func deleteScheduleEvent(se models.ScheduleEvent, w http.ResponseWriter) error { // Check if the schedule event is still in use by device reports var dr []models.DeviceReport - if err := getDeviceReportsByScheduleEventName(&dr, se.Name); err != nil { + if err := db.getDeviceReportsByScheduleEventName(&dr, se.Name); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -406,7 +406,7 @@ func deleteScheduleEvent(se models.ScheduleEvent, w http.ResponseWriter) error { return err } - if err := deleteById(SECOL, se.Id.Hex()); err != nil { + if err := db.deleteScheduleEvent(se); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -423,7 +423,7 @@ func restGetScheduleEventById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.ScheduleEvent - err := getScheduleEventById(&res, did) + err := db.getScheduleEventById(&res, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule event not found", http.StatusNotFound) @@ -447,7 +447,7 @@ func restGetScheduleEventByAddressableId(w http.ResponseWriter, r *http.Request) // Check if the addressable exists var a models.Addressable - if err := getAddressableById(&a, aid); err != nil { + if err := db.getAddressableById(&a, aid); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found for schedule event", http.StatusNotFound) loggingClient.Error("Addressable not found for schedule event: "+err.Error(), "") @@ -459,7 +459,7 @@ func restGetScheduleEventByAddressableId(w http.ResponseWriter, r *http.Request) } // Get the schedule events - if err := getScheduleEventsByAddressableId(&res, aid); err != nil { + if err := db.getScheduleEventsByAddressableId(&res, aid); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting schedule events: "+err.Error(), "") return @@ -483,7 +483,7 @@ func restGetScheduleEventByAddressableName(w http.ResponseWriter, r *http.Reques // Check if the addressable exists var a models.Addressable - if err = getAddressableByName(&a, an); err != nil { + if err = db.getAddressableByName(&a, an); err != nil { if err == mgo.ErrNotFound { loggingClient.Error("Addressable not found for schedule event: "+err.Error(), "") http.Error(w, "Addressable not found for schedule event", http.StatusNotFound) @@ -495,7 +495,7 @@ func restGetScheduleEventByAddressableName(w http.ResponseWriter, r *http.Reques } // Get the schedule events - if err = getScheduleEventsByAddressableId(&res, a.Id.Hex()); err != nil { + if err = db.getScheduleEventsByAddressableId(&res, a.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting schedule events: "+err.Error(), "") return @@ -519,7 +519,7 @@ func restGetScheduleEventsByServiceName(w http.ResponseWriter, r *http.Request) // Check if the service exists var ds models.DeviceService - if err = getDeviceServiceByName(&ds, sn); err != nil { + if err = db.getDeviceServiceByName(&ds, sn); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Service not found for schedule event", http.StatusNotFound) loggingClient.Error("Device service not found for schedule event: "+err.Error(), "") @@ -531,7 +531,7 @@ func restGetScheduleEventsByServiceName(w http.ResponseWriter, r *http.Request) } // Get the schedule events - if err = getScheduleEventsByServiceName(&res, sn); err != nil { + if err = db.getScheduleEventsByServiceName(&res, sn); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting schedule events: "+err.Error(), "") return @@ -543,7 +543,7 @@ func restGetScheduleEventsByServiceName(w http.ResponseWriter, r *http.Request) func restGetAllSchedules(w http.ResponseWriter, _ *http.Request) { res := make([]models.Schedule, 0) - err := getAllSchedules(&res) + err := db.getAllSchedules(&res) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -575,7 +575,7 @@ func restAddSchedule(w http.ResponseWriter, r *http.Request) { // Check if the name is unique var checkS models.Schedule - if err := getScheduleByName(&checkS, s.Name); err != nil { + if err := db.getScheduleByName(&checkS, s.Name); err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Schedule not found: "+err.Error(), "") @@ -612,7 +612,7 @@ func restAddSchedule(w http.ResponseWriter, r *http.Request) { } } - if err := addSchedule(&s); err != nil { + if err := db.addSchedule(&s); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem adding schedule: "+err.Error(), "") return @@ -642,9 +642,9 @@ func restUpdateSchedule(w http.ResponseWriter, r *http.Request) { // Check if the schedule exists var to models.Schedule // Try by ID - if err := getScheduleById(&to, from.Id.Hex()); err != nil { + if err := db.getScheduleById(&to, from.Id.Hex()); err != nil { // Try by name - if err = getScheduleByName(&to, from.Name); err != nil { + if err = db.getScheduleByName(&to, from.Name); err != nil { loggingClient.Error("Schedule not found: "+err.Error(), "") http.Error(w, "Schedule not found", http.StatusNotFound) return @@ -656,7 +656,7 @@ func restUpdateSchedule(w http.ResponseWriter, r *http.Request) { return } - if err := updateSchedule(to); err != nil { + if err := db.updateSchedule(to); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem updating schedule: "+err.Error(), "") return @@ -709,7 +709,7 @@ func updateScheduleFields(from models.Schedule, to *models.Schedule, w http.Resp if from.Name != "" && from.Name != to.Name { // Check if new name is unique var checkS models.Schedule - if err := getScheduleByName(&checkS, from.Name); err != nil { + if err := db.getScheduleByName(&checkS, from.Name); err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) } @@ -744,7 +744,7 @@ func restGetScheduleById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var sid string = vars[ID] var res models.Schedule - err := getScheduleById(&res, sid) + err := db.getScheduleById(&res, sid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found", http.StatusNotFound) @@ -770,7 +770,7 @@ func restGetScheduleByName(w http.ResponseWriter, r *http.Request) { } var res models.Schedule - err = getScheduleByName(&res, n) + err = db.getScheduleByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found", http.StatusNotFound) @@ -792,7 +792,7 @@ func restDeleteScheduleById(w http.ResponseWriter, r *http.Request) { // Check if the schedule exists var s models.Schedule - if err := getScheduleById(&s, id); err != nil { + if err := db.getScheduleById(&s, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found", http.StatusNotFound) loggingClient.Error("Schedule not found: "+err.Error(), "") @@ -823,7 +823,7 @@ func restDeleteScheduleByName(w http.ResponseWriter, r *http.Request) { // Check if the schedule exists var s models.Schedule - if err = getScheduleByName(&s, n); err != nil { + if err = db.getScheduleByName(&s, n); err != nil { if err == mgo.ErrNotFound { loggingClient.Error("Schedule not found: "+err.Error(), "") http.Error(w, "Schedule not found", http.StatusNotFound) @@ -857,7 +857,7 @@ func deleteSchedule(s models.Schedule, w http.ResponseWriter) error { return err } - if err := deleteById(SCOL, s.Id.Hex()); err != nil { + if err := db.deleteSchedule(s); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -873,7 +873,7 @@ func deleteSchedule(s models.Schedule, w http.ResponseWriter) error { // Determine if the scheule is still in use by schedule events func isScheduleStillInUse(s models.Schedule) (bool, error) { var scheduleEvents []models.ScheduleEvent - if err := getScheduleEventsByScheduleName(&scheduleEvents, s.Name); err != nil { + if err := db.getScheduleEventsByScheduleName(&scheduleEvents, s.Name); err != nil { return false, err } if len(scheduleEvents) > 0 { @@ -887,7 +887,7 @@ func isScheduleStillInUse(s models.Schedule) (bool, error) { func notifyScheduleAssociates(s models.Schedule, action string) error { // Get the associated schedule events var events []models.ScheduleEvent - if err := getScheduleEventsByScheduleName(&events, s.Name); err != nil { + if err := db.getScheduleEventsByScheduleName(&events, s.Name); err != nil { return err } @@ -895,7 +895,7 @@ func notifyScheduleAssociates(s models.Schedule, action string) error { var services []models.DeviceService for _, se := range events { var ds models.DeviceService - if err := getDeviceServiceByName(&ds, se.Service); err != nil { + if err := db.getDeviceServiceByName(&ds, se.Service); err != nil { return err } services = append(services, ds) @@ -913,7 +913,7 @@ func notifyScheduleAssociates(s models.Schedule, action string) error { func notifyScheduleEventAssociates(se models.ScheduleEvent, action string) error { // Get the associated device service var ds models.DeviceService - if err := getDeviceServiceByName(&ds, se.Service); err != nil { + if err := db.getDeviceServiceByName(&ds, se.Service); err != nil { return err } From 410d0046866fd58f11551647ee5e01d9203b2ad8 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Mon, 4 Jun 2018 14:47:06 +0200 Subject: [PATCH 02/10] metadata: check that db type is mongo before getting a session Signed-off-by: Federico Claramonte --- core/metadata/mongoOps.go | 8 ++++++-- core/metadata/mongo_device.go | 5 +++++ core/metadata/mongo_deviceprofile.go | 5 +++++ core/metadata/mongo_deviceservice.go | 5 +++++ core/metadata/mongo_provisionwatcher.go | 5 +++++ core/metadata/mongo_scheduleevent.go | 5 +++++ 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/core/metadata/mongoOps.go b/core/metadata/mongoOps.go index bf2cb88dfc..101956fe1a 100644 --- a/core/metadata/mongoOps.go +++ b/core/metadata/mongoOps.go @@ -31,8 +31,12 @@ type mongoDB struct { } func getMongoSessionCopy() *mgo.Session { - m := db.(*mongoDB) - return m.s.Copy() + m, ok := db.(*mongoDB) + if ok { + return m.s.Copy() + } else { + return nil + } } func (m *mongoDB) Connect() error { diff --git a/core/metadata/mongo_device.go b/core/metadata/mongo_device.go index 60b911eaf4..88c72f6857 100644 --- a/core/metadata/mongo_device.go +++ b/core/metadata/mongo_device.go @@ -14,6 +14,8 @@ package metadata import ( + "fmt" + "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -95,6 +97,9 @@ func (md *MongoDevice) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields s := getMongoSessionCopy() + if s == nil { + return fmt.Errorf("Could not obtain a mongo session") + } defer s.Close() addCol := s.DB(DB).C(ADDCOL) diff --git a/core/metadata/mongo_deviceprofile.go b/core/metadata/mongo_deviceprofile.go index 0b500fb65a..9200b9d6f8 100644 --- a/core/metadata/mongo_deviceprofile.go +++ b/core/metadata/mongo_deviceprofile.go @@ -14,6 +14,8 @@ package metadata import ( + "fmt" + "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -105,6 +107,9 @@ func (mdp *MongoDeviceProfile) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields s := getMongoSessionCopy() + if s == nil { + return fmt.Errorf("Could not obtain a mongo session") + } defer s.Close() comCol := s.DB(DB).C(COMCOL) diff --git a/core/metadata/mongo_deviceservice.go b/core/metadata/mongo_deviceservice.go index 0bc81a248e..4c4bb39e29 100644 --- a/core/metadata/mongo_deviceservice.go +++ b/core/metadata/mongo_deviceservice.go @@ -14,6 +14,8 @@ package metadata import ( + "fmt" + "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -81,6 +83,9 @@ func (mds *MongoDeviceService) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields s := getMongoSessionCopy() + if s == nil { + return fmt.Errorf("Could not obtain a mongo session") + } defer s.Close() addCol := s.DB(DB).C(ADDCOL) diff --git a/core/metadata/mongo_provisionwatcher.go b/core/metadata/mongo_provisionwatcher.go index c80431d715..77026ab35a 100644 --- a/core/metadata/mongo_provisionwatcher.go +++ b/core/metadata/mongo_provisionwatcher.go @@ -14,6 +14,8 @@ package metadata import ( + "fmt" + "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -72,6 +74,9 @@ func (mpw *MongoProvisionWatcher) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields s := getMongoSessionCopy() + if s == nil { + return fmt.Errorf("Could not obtain a mongo session") + } defer s.Close() profCol := s.DB(DB).C(DPCOL) diff --git a/core/metadata/mongo_scheduleevent.go b/core/metadata/mongo_scheduleevent.go index 09fd310fc2..06f8f0b365 100644 --- a/core/metadata/mongo_scheduleevent.go +++ b/core/metadata/mongo_scheduleevent.go @@ -14,6 +14,8 @@ package metadata import ( + "fmt" + "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -73,6 +75,9 @@ func (mse *MongoScheduleEvent) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields s := getMongoSessionCopy() + if s == nil { + return fmt.Errorf("Could not obtain a mongo session") + } defer s.Close() addCol := s.DB(DB).C(ADDCOL) From 50d46abf602a2831624f0442d2959c0da4e092fb Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Tue, 5 Jun 2018 14:41:20 +0200 Subject: [PATCH 03/10] core: Create a new package for db access Moved the core-data db functions to core/db Signed-off-by: Federico Claramonte --- core/data/clients/database-client.go | 47 --------- core/data/event.go | 12 +-- core/data/event_test.go | 4 +- core/data/init.go | 43 ++++++-- core/data/reading.go | 16 +-- core/data/valuedescriptor.go | 21 ++-- core/db/db.go | 37 +++++++ .../clients => db/influx}/influx-client.go | 69 ++++++------- .../clients => db/memory}/memory-database.go | 99 ++++++++++--------- core/db/memory/memory-database_test.go | 18 ++++ .../clients => db/mongo}/mongo-client.go | 97 +++++++++--------- .../clients => db/mongo}/mongo-client_test.go | 12 ++- .../MongoEvent.go => db/mongo/mongoevent.go} | 8 +- .../memory-database_test.go => db/test/db.go} | 17 ++-- 14 files changed, 269 insertions(+), 231 deletions(-) create mode 100644 core/db/db.go rename core/{data/clients => db/influx}/influx-client.go (92%) rename core/{data/clients => db/memory}/memory-database.go (72%) create mode 100644 core/db/memory/memory-database_test.go rename core/{data/clients => db/mongo}/mongo-client.go (85%) rename core/{data/clients => db/mongo}/mongo-client_test.go (81%) rename core/{data/clients/MongoEvent.go => db/mongo/mongoevent.go} (92%) rename core/{data/clients/memory-database_test.go => db/test/db.go} (97%) diff --git a/core/data/clients/database-client.go b/core/data/clients/database-client.go index da8c71f98e..2ca960c3d8 100644 --- a/core/data/clients/database-client.go +++ b/core/data/clients/database-client.go @@ -14,10 +14,7 @@ package clients import ( - "errors" - "github.com/edgexfoundry/edgex-go/core/domain/models" - "github.com/edgexfoundry/edgex-go/support/logging-client" "gopkg.in/mgo.v2/bson" ) @@ -193,47 +190,3 @@ type DBClient interface { ScrubAllValueDescriptors() error } -type DBConfiguration struct { - DbType DatabaseType - Host string - Port int - Timeout int - DatabaseName string - Username string - Password string -} - -var ErrNotFound error = errors.New("Item not found") -var ErrUnsupportedDatabase error = errors.New("Unsuppored database type") -var ErrInvalidObjectId error = errors.New("Invalid object ID") -var ErrNotUnique error = errors.New("Resource already exists") -var DataClient = "dataClient" -var loggingClient = logger.NewClient(DataClient, false, "") - -// Return the dbClient interface -func NewDBClient(config DBConfiguration) (DBClient, error) { - switch config.DbType { - case MONGO: - // Create the mongo client - mc, err := newMongoClient(config) - if err != nil { - loggingClient.Error("Error creating the mongo client: " + err.Error()) - return nil, err - } - return mc, nil - case INFLUX: - // Create the influx client - ic, err := newInfluxClient(config) - if err != nil { - loggingClient.Error("Error creating the influx client: " + err.Error()) - return nil, err - } - return ic, nil - case MEMORY: - // Create the memory client - mem := &memDB{} - return mem, nil - default: - return nil, ErrUnsupportedDatabase - } -} diff --git a/core/data/event.go b/core/data/event.go index 3bfc97f2d7..24a8ed4979 100644 --- a/core/data/event.go +++ b/core/data/event.go @@ -22,7 +22,7 @@ import ( "time" "github.com/edgexfoundry/edgex-go/core/clients/types" - "github.com/edgexfoundry/edgex-go/core/data/clients" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" ) @@ -215,7 +215,7 @@ func eventHandler(w http.ResponseWriter, r *http.Request) { // Check value descriptor vd, err := dbc.ValueDescriptorByName(e.Readings[reading].Name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor for a reading not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -269,7 +269,7 @@ func eventHandler(w http.ResponseWriter, r *http.Request) { // Check if the event exists to, err := dbc.EventById(from.ID.Hex()) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Event not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -327,7 +327,7 @@ func getEventByIdHandler(w http.ResponseWriter, r *http.Request) { // Get the event e, err := dbc.EventById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Event not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -421,7 +421,7 @@ func eventIdHandler(w http.ResponseWriter, r *http.Request) { // Check if the event exists e, err := dbc.EventById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Event not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -448,7 +448,7 @@ func eventIdHandler(w http.ResponseWriter, r *http.Request) { // Check if the event exists e, err := dbc.EventById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Event not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) diff --git a/core/data/event_test.go b/core/data/event_test.go index 55da81eee5..04ba6b107a 100644 --- a/core/data/event_test.go +++ b/core/data/event_test.go @@ -22,7 +22,7 @@ import ( "strconv" "testing" - "github.com/edgexfoundry/edgex-go/core/data/clients" + "github.com/edgexfoundry/edgex-go/core/db/memory" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/edgexfoundry/edgex-go/support/logging-client" "github.com/gorilla/mux" @@ -34,7 +34,7 @@ var testRoutes *mux.Router func TestMain(m *testing.M) { testEvent.Device = "test device" testEvent.Origin = 123456789 - dbc, _ = clients.NewDBClient(clients.DBConfiguration{DbType: clients.MEMORY}) + dbc = &memory.MemDB{} testEvent.ID, _ = dbc.AddEvent(&testEvent) testRoutes = LoadRestRoutes() loggingClient = logger.NewMockClient() diff --git a/core/data/init.go b/core/data/init.go index 5a79e39b2d..484835359e 100644 --- a/core/data/init.go +++ b/core/data/init.go @@ -21,6 +21,10 @@ import ( "github.com/edgexfoundry/edgex-go/core/clients/types" "github.com/edgexfoundry/edgex-go/core/data/clients" "github.com/edgexfoundry/edgex-go/core/data/messaging" + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/db/influx" + "github.com/edgexfoundry/edgex-go/core/db/memory" + "github.com/edgexfoundry/edgex-go/core/db/mongo" "github.com/edgexfoundry/edgex-go/internal" consulclient "github.com/edgexfoundry/edgex-go/support/consul-client" "github.com/edgexfoundry/edgex-go/support/logging-client" @@ -57,6 +61,34 @@ func ConnectToConsul(conf ConfigurationStruct) error { return nil } +// Return the dbClient interface +func newDBClient(dbType clients.DatabaseType, config db.Configuration) (clients.DBClient, error) { + switch dbType { + case clients.MONGO: + // Create the mongo client + mc, err := mongo.NewClient(config) + if err != nil { + loggingClient.Error("Error creating the mongo client: " + err.Error()) + return nil, err + } + return mc, nil + case clients.INFLUX: + // Create the influx client + ic, err := influx.NewClient(config) + if err != nil { + loggingClient.Error("Error creating the influx client: " + err.Error()) + return nil, err + } + return ic, nil + case clients.MEMORY: + // Create the memory client + mem := &memory.MemDB{} + return mem, nil + default: + return nil, db.ErrUnsupportedDatabase + } +} + func Init(conf ConfigurationStruct, l logger.LoggingClient, useConsul bool) error { loggingClient = l configuration = conf @@ -65,8 +97,7 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient, useConsul bool) erro var err error // Create a database client - dbc, err = clients.NewDBClient(clients.DBConfiguration{ - DbType: clients.MONGO, + dbc, err = newDBClient(clients.MONGO, db.Configuration{ Host: conf.MongoDBHost, Port: conf.MongoDBPort, Timeout: conf.MongoDBConnectTimeout, @@ -80,10 +111,10 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient, useConsul bool) erro // Create metadata clients params := types.EndpointParams{ - ServiceKey:internal.CoreMetaDataServiceKey, - Path:conf.MetaDevicePath, - UseRegistry:useConsul, - Url:conf.MetaDeviceURL} + ServiceKey: internal.CoreMetaDataServiceKey, + Path: conf.MetaDevicePath, + UseRegistry: useConsul, + Url: conf.MetaDeviceURL} mdc = metadata.NewDeviceClient(params, types.Endpoint{}) diff --git a/core/data/reading.go b/core/data/reading.go index fd18ae0387..ee7419d3fd 100644 --- a/core/data/reading.go +++ b/core/data/reading.go @@ -20,7 +20,7 @@ import ( "net/url" "strconv" - "github.com/edgexfoundry/edgex-go/core/data/clients" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" ) @@ -63,7 +63,7 @@ func readingHandler(w http.ResponseWriter, r *http.Request) { // Check the value descriptor vd, err := dbc.ValueDescriptorByName(reading.Name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found for reading", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -116,7 +116,7 @@ func readingHandler(w http.ResponseWriter, r *http.Request) { // Check if the reading exists to, err := dbc.ReadingById(from.Id.Hex()) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Reading not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -141,7 +141,7 @@ func readingHandler(w http.ResponseWriter, r *http.Request) { // Check the value descriptor vd, err := dbc.ValueDescriptorByName(to.Name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found for reading", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -187,7 +187,7 @@ func getReadingByIdHandler(w http.ResponseWriter, r *http.Request) { case http.MethodGet: reading, err := dbc.ReadingById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Reading not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -235,7 +235,7 @@ func deleteReadingByIdHandler(w http.ResponseWriter, r *http.Request) { // Check if the reading exists reading, err := dbc.ReadingById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Reading not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -329,7 +329,7 @@ func readingbyValueDescriptorHandler(w http.ResponseWriter, r *http.Request) { if configuration.ValidateCheck { _, err = dbc.ValueDescriptorByName(name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found for reading", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -601,7 +601,7 @@ func readingByValueDescriptorAndDeviceHandler(w http.ResponseWriter, r *http.Req if configuration.ValidateCheck { _, err = dbc.ValueDescriptorByName(name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found for reading", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) diff --git a/core/data/valuedescriptor.go b/core/data/valuedescriptor.go index e0dd724ac3..bf51efcb4a 100644 --- a/core/data/valuedescriptor.go +++ b/core/data/valuedescriptor.go @@ -20,11 +20,12 @@ import ( "net/url" "regexp" + "fmt" + "github.com/edgexfoundry/edgex-go/core/clients/types" - "github.com/edgexfoundry/edgex-go/core/data/clients" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" - "fmt" ) const ( @@ -91,7 +92,7 @@ func valueDescriptorHandler(w http.ResponseWriter, r *http.Request) { id, err := dbc.AddValueDescriptor(v) if err != nil { - if err == clients.ErrNotUnique { + if err == db.ErrNotUnique { http.Error(w, "Value Descriptor already exists", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -118,7 +119,7 @@ func valueDescriptorHandler(w http.ResponseWriter, r *http.Request) { if err != nil { to, err = dbc.ValueDescriptorByName(from.Name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -187,7 +188,7 @@ func valueDescriptorHandler(w http.ResponseWriter, r *http.Request) { // Push the updated valuedescriptor to the database err = dbc.UpdateValueDescriptor(to) if err != nil { - if err == clients.ErrNotUnique { + if err == db.ErrNotUnique { http.Error(w, "Value descriptor name is not unique", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -215,7 +216,7 @@ func deleteValueDescriptorByIdHandler(w http.ResponseWriter, r *http.Request) { // Check if the value descriptor exists vd, err := dbc.ValueDescriptorById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -252,7 +253,7 @@ func valueDescriptorByNameHandler(w http.ResponseWriter, r *http.Request) { case http.MethodGet: v, err := dbc.ValueDescriptorByName(name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value Descriptor not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -266,7 +267,7 @@ func valueDescriptorByNameHandler(w http.ResponseWriter, r *http.Request) { // Check if the value descriptor exists vd, err := dbc.ValueDescriptorByName(name) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value Descriptor not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -323,7 +324,7 @@ func valueDescriptorByIdHandler(w http.ResponseWriter, r *http.Request) { case http.MethodGet: v, err := dbc.ValueDescriptorById(id) if err != nil { - if err == clients.ErrNotFound { + if err == db.ErrNotFound { http.Error(w, "Value descriptor not found", http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -476,7 +477,7 @@ func valueDescriptorsForDevice(d models.Device, w http.ResponseWriter) ([]models vd, err := dbc.ValueDescriptorByName(name) // Not an error if not found - if err == clients.ErrNotFound { + if err == db.ErrNotFound { continue } diff --git a/core/db/db.go b/core/db/db.go new file mode 100644 index 0000000000..88ce61b9b0 --- /dev/null +++ b/core/db/db.go @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright 2018 Dell Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ + +package db + +import "errors" + +const ( + EventsCollection = "event" + ReadingsCollection = "reading" + ValueDescriptorCollection = "valueDescriptor" +) + +var ErrNotFound error = errors.New("Item not found") +var ErrUnsupportedDatabase error = errors.New("Unsuppored database type") +var ErrInvalidObjectId error = errors.New("Invalid object ID") +var ErrNotUnique error = errors.New("Resource already exists") + +type Configuration struct { + Host string + Port int + Timeout int + DatabaseName string + Username string + Password string +} diff --git a/core/data/clients/influx-client.go b/core/db/influx/influx-client.go similarity index 92% rename from core/data/clients/influx-client.go rename to core/db/influx/influx-client.go index 4e2c923fed..4f2f9299ca 100644 --- a/core/data/clients/influx-client.go +++ b/core/db/influx/influx-client.go @@ -12,7 +12,7 @@ * the License. *******************************************************************************/ -package clients +package influx import ( "encoding/json" @@ -21,6 +21,7 @@ import ( "strings" "time" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/influxdata/influxdb/client/v2" "gopkg.in/mgo.v2/bson" @@ -39,7 +40,7 @@ type InfluxClient struct { } // Return a pointer to the InfluxClient -func newInfluxClient(config DBConfiguration) (*InfluxClient, error) { +func NewClient(config db.Configuration) (*InfluxClient, error) { // Create the dial info for the Influx session connectionString := "http://" + config.Host + ":" + strconv.Itoa(config.Port) influxdbHTTPInfo := client.HTTPConfig{ @@ -115,7 +116,7 @@ func (ic *InfluxClient) AddEvent(e *models.Event) (bson.ObjectId, error) { e.ID = bson.NewObjectId() // Add the event - err := ic.eventToDB(ic.Database, EVENTS_COLLECTION, e, true) + err := ic.eventToDB(ic.Database, db.EventsCollection, e, true) if err != nil { return e.ID, err } @@ -130,18 +131,18 @@ func (ic *InfluxClient) UpdateEvent(e models.Event) error { e.Modified = time.Now().UnixNano() / int64(time.Millisecond) // Delete event - if err := ic.deleteById(EVENTS_COLLECTION, e.ID.Hex()); err != nil { + if err := ic.deleteById(db.EventsCollection, e.ID.Hex()); err != nil { return err } // Add the event - return ic.eventToDB(ic.Database, EVENTS_COLLECTION, &e, false) + return ic.eventToDB(ic.Database, db.EventsCollection, &e, false) } // Get an event by id func (ic *InfluxClient) EventById(id string) (models.Event, error) { if !bson.IsObjectIdHex(id) { - return models.Event{}, ErrInvalidObjectId + return models.Event{}, db.ErrInvalidObjectId } q := fmt.Sprintf("WHERE id = '%s'", id) events, err := ic.getEvents(q) @@ -153,13 +154,13 @@ func (ic *InfluxClient) EventById(id string) (models.Event, error) { // Get the number of events in Influx func (ic *InfluxClient) EventCount() (int, error) { - query := fmt.Sprintf("SELECT COUNT(*) FROM %s", EVENTS_COLLECTION) + query := fmt.Sprintf("SELECT COUNT(*) FROM %s", db.EventsCollection) return ic.getCount(query) } // Get the number of events in Influx for the device func (ic *InfluxClient) EventCountByDeviceId(id string) (int, error) { - query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE device = '%s'", EVENTS_COLLECTION, id) + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE device = '%s'", db.EventsCollection, id) return ic.getCount(query) } @@ -167,7 +168,7 @@ func (ic *InfluxClient) EventCountByDeviceId(id string) (int, error) { // 404 - Event not found // 503 - Unexpected problems func (ic *InfluxClient) DeleteEventById(id string) error { - return ic.deleteById(EVENTS_COLLECTION, id) + return ic.deleteById(db.EventsCollection, id) } // Get a list of events based on the device id and limit @@ -204,18 +205,18 @@ func (ic *InfluxClient) EventsPushed() ([]models.Event, error) { // Delete all of the readings and all of the events func (ic *InfluxClient) ScrubAllEvents() error { - err := ic.deleteAll(READINGS_COLLECTION) + err := ic.deleteAll(db.ReadingsCollection) if err != nil { return err } - return ic.deleteAll(EVENTS_COLLECTION) + return ic.deleteAll(db.EventsCollection) } // Get events for the passed query func (ic *InfluxClient) getEvents(q string) ([]models.Event, error) { events := []models.Event{} - query := fmt.Sprintf("SELECT * FROM %s %s", EVENTS_COLLECTION, q) + query := fmt.Sprintf("SELECT * FROM %s %s", db.EventsCollection, q) res, err := ic.queryDB(query) if err != nil { return events, err @@ -237,7 +238,7 @@ func (ic *InfluxClient) deleteById(collection string, id string) error { q := fmt.Sprintf("DROP SERIES FROM %s WHERE id = '%s'", collection, id) _, err := ic.queryDB(q) if err != nil { - return ErrNotFound + return db.ErrNotFound } return nil } @@ -251,9 +252,9 @@ func (ic *InfluxClient) deleteAll(collection string) error { return nil } -func (ic *InfluxClient) eventToDB(db string, collection string, e *models.Event, addReadings bool) error { +func (ic *InfluxClient) eventToDB(dbStr string, collection string, e *models.Event, addReadings bool) error { bp, err := client.NewBatchPoints(client.BatchPointsConfig{ - Database: db, + Database: dbStr, Precision: "us", }) if err != nil { @@ -282,7 +283,7 @@ func (ic *InfluxClient) eventToDB(db string, collection string, e *models.Event, } pt, err := client.NewPoint( - READINGS_COLLECTION, + db.ReadingsCollection, tags, fields, time.Now(), @@ -396,7 +397,7 @@ func (ic *InfluxClient) AddReading(r models.Reading) (bson.ObjectId, error) { // Get the reading ready r.Id = bson.NewObjectId() r.Created = time.Now().UnixNano() / int64(time.Millisecond) - err := ic.addReadingToDB(ic.Database, READINGS_COLLECTION, &r) + err := ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) return r.Id, err } @@ -408,19 +409,19 @@ func (ic *InfluxClient) UpdateReading(r models.Reading) error { r.Modified = time.Now().UnixNano() / int64(time.Millisecond) // Delete reading - if err := ic.deleteById(READINGS_COLLECTION, r.Id.Hex()); err != nil { + if err := ic.deleteById(db.ReadingsCollection, r.Id.Hex()); err != nil { return err } // Add the reading - return ic.addReadingToDB(ic.Database, READINGS_COLLECTION, &r) + return ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) } // Get a reading by ID func (ic *InfluxClient) ReadingById(id string) (models.Reading, error) { // Check if the id is a id hex if !bson.IsObjectIdHex(id) { - return models.Reading{}, ErrInvalidObjectId + return models.Reading{}, db.ErrInvalidObjectId } query := fmt.Sprintf("WHERE id = '%s'", id) @@ -430,14 +431,14 @@ func (ic *InfluxClient) ReadingById(id string) (models.Reading, error) { // Get the count of readings in Influx func (ic *InfluxClient) ReadingCount() (int, error) { - query := fmt.Sprintf("SELECT COUNT(*) FROM %s", READINGS_COLLECTION) + query := fmt.Sprintf("SELECT COUNT(*) FROM %s", db.ReadingsCollection) return ic.getCount(query) } // Delete a reading by ID // 404 - can't find the reading with the given id func (ic *InfluxClient) DeleteReadingById(id string) error { - return ic.deleteById(READINGS_COLLECTION, id) + return ic.deleteById(db.ReadingsCollection, id) } // Return a list of readings for the given device (id or name) @@ -485,7 +486,7 @@ func (ic *InfluxClient) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescri // Get readings for the passed query func (ic *InfluxClient) getReadings(q string) ([]models.Reading, error) { readings := []models.Reading{} - query := fmt.Sprintf("SELECT * FROM %s %s", READINGS_COLLECTION, q) + query := fmt.Sprintf("SELECT * FROM %s %s", db.ReadingsCollection, q) res, err := ic.queryDB(query) if err != nil { return readings, err @@ -601,7 +602,7 @@ func (ic *InfluxClient) AddValueDescriptor(v models.ValueDescriptor) (bson.Objec v.Created = time.Now().UnixNano() / int64(time.Millisecond) // See if the name is unique and add the value descriptors - query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE 'name' = '%s'", VALUE_DESCRIPTOR_COLLECTION, v.Name) + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE 'name' = '%s'", db.ValueDescriptorCollection, v.Name) num, err := ic.getCount(query) if err != nil { return v.Id, err @@ -609,14 +610,14 @@ func (ic *InfluxClient) AddValueDescriptor(v models.ValueDescriptor) (bson.Objec // Duplicate name if num != 0 { - return v.Id, ErrNotUnique + return v.Id, db.ErrNotUnique } // Set id v.Id = bson.NewObjectId() // Add Value Descriptor - err = ic.addValueDescriptorToDB(ic.Database, VALUE_DESCRIPTOR_COLLECTION, &v) + err = ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) if err != nil { return v.Id, err } @@ -636,15 +637,15 @@ func (ic *InfluxClient) ValueDescriptors() ([]models.ValueDescriptor, error) { // 404 not found if the value descriptor cannot be found by the identifiers func (ic *InfluxClient) UpdateValueDescriptor(v models.ValueDescriptor) error { // See if the name is unique if it changed - query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE id = '%s'", VALUE_DESCRIPTOR_COLLECTION, v.Id) + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE id = '%s'", db.ValueDescriptorCollection, v.Id) num, err := ic.getCount(query) if err != nil { return err } if num != 0 { - return ErrNotUnique + return db.ErrNotUnique } - query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE name = '%s'", VALUE_DESCRIPTOR_COLLECTION, v.Name) + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE name = '%s'", db.ValueDescriptorCollection, v.Name) num, err = ic.getCount(query) if err != nil { return err @@ -659,7 +660,7 @@ func (ic *InfluxClient) UpdateValueDescriptor(v models.ValueDescriptor) error { v.Modified = time.Now().UnixNano() / int64(time.Millisecond) // Delete Value Descriptor // Add Value Descriptor - return ic.addValueDescriptorToDB(ic.Database, VALUE_DESCRIPTOR_COLLECTION, &v) + return ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) } // Delete the value descriptor based on the id @@ -702,7 +703,7 @@ func (ic *InfluxClient) ValueDescriptorsByName(names []string) ([]models.ValueDe // Return NotFoundError if there is no value descriptor for the id func (ic *InfluxClient) ValueDescriptorById(id string) (models.ValueDescriptor, error) { if !bson.IsObjectIdHex(id) { - return models.ValueDescriptor{}, ErrInvalidObjectId + return models.ValueDescriptor{}, db.ErrInvalidObjectId } query := fmt.Sprintf("WHERE id = '%s'", id) @@ -733,11 +734,11 @@ func (ic *InfluxClient) ValueDescriptorsByType(t string) ([]models.ValueDescript // Delete all of the value descriptors func (ic *InfluxClient) ScrubAllValueDescriptors() error { - return ic.deleteAll(VALUE_DESCRIPTOR_COLLECTION) + return ic.deleteAll(db.ValueDescriptorCollection) } func (ic *InfluxClient) deleteValueDescriptorBy(query string) error { - q := fmt.Sprintf("DELETE FROM %s %s", VALUE_DESCRIPTOR_COLLECTION, query) + q := fmt.Sprintf("DELETE FROM %s %s", db.ValueDescriptorCollection, query) _, err := ic.queryDB(q) if err != nil { return err @@ -748,7 +749,7 @@ func (ic *InfluxClient) deleteValueDescriptorBy(query string) error { // Get value descriptors for the passed query func (ic *InfluxClient) getValueDescriptors(q string) ([]models.ValueDescriptor, error) { vds := []models.ValueDescriptor{} - query := fmt.Sprintf("SELECT * FROM %s %s", VALUE_DESCRIPTOR_COLLECTION, q) + query := fmt.Sprintf("SELECT * FROM %s %s", db.ValueDescriptorCollection, q) res, err := ic.queryDB(query) if err != nil { return vds, err diff --git a/core/data/clients/memory-database.go b/core/db/memory/memory-database.go similarity index 72% rename from core/data/clients/memory-database.go rename to core/db/memory/memory-database.go index 5a7f0988f6..cdd3edc0ce 100644 --- a/core/data/clients/memory-database.go +++ b/core/db/memory/memory-database.go @@ -11,25 +11,26 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package clients +package memory import ( "time" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2/bson" ) -type memDB struct { +type MemDB struct { readings []models.Reading events []models.Event vDescriptors []models.ValueDescriptor } -func (m *memDB) CloseSession() { +func (m *MemDB) CloseSession() { } -func (m *memDB) AddReading(r models.Reading) (bson.ObjectId, error) { +func (m *MemDB) AddReading(r models.Reading) (bson.ObjectId, error) { currentTime := time.Now().UnixNano() / int64(time.Millisecond) r.Created = currentTime r.Modified = currentTime @@ -40,11 +41,11 @@ func (m *memDB) AddReading(r models.Reading) (bson.ObjectId, error) { return r.Id, nil } -func (m *memDB) Events() ([]models.Event, error) { +func (m *MemDB) Events() ([]models.Event, error) { return m.events, nil } -func (m *memDB) AddEvent(e *models.Event) (bson.ObjectId, error) { +func (m *MemDB) AddEvent(e *models.Event) (bson.ObjectId, error) { currentTime := time.Now().UnixNano() / int64(time.Millisecond) for i := range e.Readings { @@ -64,30 +65,30 @@ func (m *memDB) AddEvent(e *models.Event) (bson.ObjectId, error) { return e.ID, nil } -func (m *memDB) UpdateEvent(event models.Event) error { +func (m *MemDB) UpdateEvent(event models.Event) error { for i, e := range m.events { if e.ID == event.ID { m.events[i] = event return nil } } - return ErrNotFound + return db.ErrNotFound } -func (m *memDB) EventById(id string) (models.Event, error) { +func (m *MemDB) EventById(id string) (models.Event, error) { for _, e := range m.events { if e.ID.Hex() == id { return e, nil } } - return models.Event{}, ErrNotFound + return models.Event{}, db.ErrNotFound } -func (m *memDB) EventCount() (int, error) { +func (m *MemDB) EventCount() (int, error) { return len(m.events), nil } -func (m *memDB) EventCountByDeviceId(id string) (int, error) { +func (m *MemDB) EventCountByDeviceId(id string) (int, error) { count := 0 for _, e := range m.events { if e.Device == id { @@ -97,17 +98,17 @@ func (m *memDB) EventCountByDeviceId(id string) (int, error) { return count, nil } -func (m *memDB) DeleteEventById(id string) error { +func (m *MemDB) DeleteEventById(id string) error { for i, e := range m.events { if e.ID.Hex() == id { m.events = append(m.events[:i], m.events[i+1:]...) return nil } } - return ErrNotFound + return db.ErrNotFound } -func (m *memDB) EventsForDeviceLimit(id string, limit int) ([]models.Event, error) { +func (m *MemDB) EventsForDeviceLimit(id string, limit int) ([]models.Event, error) { events := []models.Event{} count := 0 for _, e := range m.events { @@ -122,7 +123,7 @@ func (m *memDB) EventsForDeviceLimit(id string, limit int) ([]models.Event, erro return events, nil } -func (m *memDB) EventsForDevice(id string) ([]models.Event, error) { +func (m *MemDB) EventsForDevice(id string) ([]models.Event, error) { events := []models.Event{} for _, e := range m.events { if e.Device == id { @@ -132,7 +133,7 @@ func (m *memDB) EventsForDevice(id string) ([]models.Event, error) { return events, nil } -func (m *memDB) EventsByCreationTime(startTime, endTime int64, limit int) ([]models.Event, error) { +func (m *MemDB) EventsByCreationTime(startTime, endTime int64, limit int) ([]models.Event, error) { events := []models.Event{} count := 0 for _, e := range m.events { @@ -147,7 +148,7 @@ func (m *memDB) EventsByCreationTime(startTime, endTime int64, limit int) ([]mod return events, nil } -func (m *memDB) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor string, limit int) ([]models.Reading, error) { +func (m *MemDB) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor string, limit int) ([]models.Reading, error) { readings := []models.Reading{} count := 0 for _, r := range m.readings { @@ -162,7 +163,7 @@ func (m *memDB) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor str return readings, nil } -func (m *memDB) EventsOlderThanAge(age int64) ([]models.Event, error) { +func (m *MemDB) EventsOlderThanAge(age int64) ([]models.Event, error) { currentTime := time.Now().UnixNano() / int64(time.Millisecond) events := []models.Event{} for _, e := range m.events { @@ -173,7 +174,7 @@ func (m *memDB) EventsOlderThanAge(age int64) ([]models.Event, error) { return events, nil } -func (m *memDB) EventsPushed() ([]models.Event, error) { +func (m *MemDB) EventsPushed() ([]models.Event, error) { events := []models.Event{} for _, e := range m.events { if e.Pushed != 0 { @@ -183,50 +184,50 @@ func (m *memDB) EventsPushed() ([]models.Event, error) { return events, nil } -func (m *memDB) ScrubAllEvents() error { +func (m *MemDB) ScrubAllEvents() error { m.events = nil m.readings = nil return nil } -func (m *memDB) Readings() ([]models.Reading, error) { +func (m *MemDB) Readings() ([]models.Reading, error) { return m.readings, nil } -func (m *memDB) UpdateReading(reading models.Reading) error { +func (m *MemDB) UpdateReading(reading models.Reading) error { for i, r := range m.readings { if r.Id == reading.Id { m.readings[i] = reading return nil } } - return ErrNotFound + return db.ErrNotFound } -func (m *memDB) ReadingById(id string) (models.Reading, error) { +func (m *MemDB) ReadingById(id string) (models.Reading, error) { for _, r := range m.readings { if r.Id.Hex() == id { return r, nil } } - return models.Reading{}, ErrNotFound + return models.Reading{}, db.ErrNotFound } -func (m *memDB) ReadingCount() (int, error) { +func (m *MemDB) ReadingCount() (int, error) { return len(m.readings), nil } -func (m *memDB) DeleteReadingById(id string) error { +func (m *MemDB) DeleteReadingById(id string) error { for i, r := range m.readings { if r.Id.Hex() == id { m.readings = append(m.readings[:i], m.readings[i+1:]...) return nil } } - return ErrNotFound + return db.ErrNotFound } -func (m *memDB) ReadingsByDevice(id string, limit int) ([]models.Reading, error) { +func (m *MemDB) ReadingsByDevice(id string, limit int) ([]models.Reading, error) { readings := []models.Reading{} count := 0 for _, r := range m.readings { @@ -241,7 +242,7 @@ func (m *memDB) ReadingsByDevice(id string, limit int) ([]models.Reading, error) return readings, nil } -func (m *memDB) ReadingsByValueDescriptor(name string, limit int) ([]models.Reading, error) { +func (m *MemDB) ReadingsByValueDescriptor(name string, limit int) ([]models.Reading, error) { readings := []models.Reading{} count := 0 for _, r := range m.readings { @@ -265,7 +266,7 @@ func stringInSlice(a string, list []string) bool { return false } -func (m *memDB) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { +func (m *MemDB) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { readings := []models.Reading{} count := 0 for _, r := range m.readings { @@ -280,7 +281,7 @@ func (m *memDB) ReadingsByValueDescriptorNames(names []string, limit int) ([]mod return readings, nil } -func (m *memDB) ReadingsByCreationTime(start, end int64, limit int) ([]models.Reading, error) { +func (m *MemDB) ReadingsByCreationTime(start, end int64, limit int) ([]models.Reading, error) { readings := []models.Reading{} count := 0 for _, r := range m.readings { @@ -295,7 +296,7 @@ func (m *memDB) ReadingsByCreationTime(start, end int64, limit int) ([]models.Re return readings, nil } -func (m *memDB) AddValueDescriptor(value models.ValueDescriptor) (bson.ObjectId, error) { +func (m *MemDB) AddValueDescriptor(value models.ValueDescriptor) (bson.ObjectId, error) { currentTime := time.Now().UnixNano() / int64(time.Millisecond) value.Created = currentTime value.Modified = currentTime @@ -303,7 +304,7 @@ func (m *memDB) AddValueDescriptor(value models.ValueDescriptor) (bson.ObjectId, for _, v := range m.vDescriptors { if v.Name == value.Name { - return v.Id, ErrNotUnique + return v.Id, db.ErrNotUnique } } @@ -312,40 +313,40 @@ func (m *memDB) AddValueDescriptor(value models.ValueDescriptor) (bson.ObjectId, return value.Id, nil } -func (m *memDB) ValueDescriptors() ([]models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptors() ([]models.ValueDescriptor, error) { return m.vDescriptors, nil } -func (m *memDB) UpdateValueDescriptor(value models.ValueDescriptor) error { +func (m *MemDB) UpdateValueDescriptor(value models.ValueDescriptor) error { for i, v := range m.vDescriptors { if v.Id == value.Id { m.vDescriptors[i] = value return nil } } - return ErrNotFound + return db.ErrNotFound } -func (m *memDB) DeleteValueDescriptorById(id string) error { +func (m *MemDB) DeleteValueDescriptorById(id string) error { for i, v := range m.vDescriptors { if v.Id.Hex() == id { m.vDescriptors = append(m.vDescriptors[:i], m.vDescriptors[i+1:]...) return nil } } - return ErrNotFound + return db.ErrNotFound } -func (m *memDB) ValueDescriptorByName(name string) (models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptorByName(name string) (models.ValueDescriptor, error) { for _, v := range m.vDescriptors { if v.Name == name { return v, nil } } - return models.ValueDescriptor{}, ErrNotFound + return models.ValueDescriptor{}, db.ErrNotFound } -func (m *memDB) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor, error) { vds := []models.ValueDescriptor{} for _, v := range m.vDescriptors { if stringInSlice(v.Name, names) { @@ -355,16 +356,16 @@ func (m *memDB) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor return vds, nil } -func (m *memDB) ValueDescriptorById(id string) (models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptorById(id string) (models.ValueDescriptor, error) { for _, v := range m.vDescriptors { if v.Id.Hex() == id { return v, nil } } - return models.ValueDescriptor{}, ErrNotFound + return models.ValueDescriptor{}, db.ErrNotFound } -func (m *memDB) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescriptor, error) { vds := []models.ValueDescriptor{} for _, v := range m.vDescriptors { if v.UomLabel == uomLabel { @@ -374,7 +375,7 @@ func (m *memDB) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescr return vds, nil } -func (m *memDB) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, error) { vds := []models.ValueDescriptor{} for _, v := range m.vDescriptors { if stringInSlice(label, v.Labels) { @@ -384,7 +385,7 @@ func (m *memDB) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, return vds, nil } -func (m *memDB) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, error) { +func (m *MemDB) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, error) { vds := []models.ValueDescriptor{} for _, v := range m.vDescriptors { if v.Type == t { @@ -394,7 +395,7 @@ func (m *memDB) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, erro return vds, nil } -func (m *memDB) ScrubAllValueDescriptors() error { +func (m *MemDB) ScrubAllValueDescriptors() error { m.vDescriptors = nil return nil } diff --git a/core/db/memory/memory-database_test.go b/core/db/memory/memory-database_test.go new file mode 100644 index 0000000000..8f255aabed --- /dev/null +++ b/core/db/memory/memory-database_test.go @@ -0,0 +1,18 @@ +// +// Copyright (c) 2018 Cavium +// +// SPDX-License-Identifier: Apache-2.0 +// + +package memory + +import ( + "testing" + + "github.com/edgexfoundry/edgex-go/core/db/test" +) + +func TestMemoryDB(t *testing.T) { + memory := &MemDB{} + test.TestDataDB(t, memory) +} diff --git a/core/data/clients/mongo-client.go b/core/db/mongo/mongo-client.go similarity index 85% rename from core/data/clients/mongo-client.go rename to core/db/mongo/mongo-client.go index a5eec7fe68..13fb8bc88a 100644 --- a/core/data/clients/mongo-client.go +++ b/core/db/mongo/mongo-client.go @@ -11,24 +11,19 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package clients +package mongo import ( "errors" "strconv" "time" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) -const ( - EVENTS_COLLECTION = "event" - READINGS_COLLECTION = "reading" - VALUE_DESCRIPTOR_COLLECTION = "valueDescriptor" -) - var currentMongoClient *MongoClient // Singleton used so that MongoEvent can use it to de-reference readings /* @@ -49,10 +44,9 @@ type MongoClient struct { } // Return a pointer to the MongoClient -func newMongoClient(config DBConfiguration) (*MongoClient, error) { +func NewClient(config db.Configuration) (*MongoClient, error) { // Create the dial info for the Mongo session connectionString := config.Host + ":" + strconv.Itoa(config.Port) - loggingClient.Info("INFO: Connecting to mongo at: " + connectionString) mongoDBDialInfo := &mgo.DialInfo{ Addrs: []string{connectionString}, Timeout: time.Duration(config.Timeout) * time.Millisecond, @@ -62,7 +56,6 @@ func newMongoClient(config DBConfiguration) (*MongoClient, error) { } session, err := mgo.DialWithInfo(mongoDBDialInfo) if err != nil { - loggingClient.Error("Error dialing the mongo server: " + err.Error()) return nil, err } @@ -117,7 +110,7 @@ func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { e.Readings[i].Device = e.Device ui = append(ui, e.Readings[i]) } - err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).Insert(ui...) + err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Insert(ui...) if err != nil { return e.ID, err } @@ -127,7 +120,7 @@ func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { me := MongoEvent{Event: *e} // Add the event - err := s.DB(mc.Database.Name).C(EVENTS_COLLECTION).Insert(me) + err := s.DB(mc.Database.Name).C(db.EventsCollection).Insert(me) if err != nil { return e.ID, err } @@ -147,9 +140,9 @@ func (mc *MongoClient) UpdateEvent(e models.Event) error { // Handle DBRef me := MongoEvent{Event: e} - err := s.DB(mc.Database.Name).C(EVENTS_COLLECTION).UpdateId(me.ID, me) + err := s.DB(mc.Database.Name).C(db.EventsCollection).UpdateId(me.ID, me) if err == mgo.ErrNotFound { - return ErrNotFound + return db.ErrNotFound } return err @@ -158,7 +151,7 @@ func (mc *MongoClient) UpdateEvent(e models.Event) error { // Get an event by id func (mc *MongoClient) EventById(id string) (models.Event, error) { if !bson.IsObjectIdHex(id) { - return models.Event{}, ErrInvalidObjectId + return models.Event{}, db.ErrInvalidObjectId } return mc.getEvent(bson.M{"_id": bson.ObjectIdHex(id)}) } @@ -168,7 +161,7 @@ func (mc *MongoClient) EventCount() (int, error) { s := mc.getSessionCopy() defer s.Close() - return s.DB(mc.Database.Name).C(EVENTS_COLLECTION).Find(nil).Count() + return s.DB(mc.Database.Name).C(db.EventsCollection).Find(nil).Count() } // Get the number of events in Mongo for the device @@ -177,14 +170,14 @@ func (mc *MongoClient) EventCountByDeviceId(id string) (int, error) { defer s.Close() query := bson.M{"device": id} - return s.DB(mc.Database.Name).C(EVENTS_COLLECTION).Find(query).Count() + return s.DB(mc.Database.Name).C(db.EventsCollection).Find(query).Count() } // Delete an event by ID and all of its readings // 404 - Event not found // 503 - Unexpected problems func (mc *MongoClient) DeleteEventById(id string) error { - return mc.deleteById(id, EVENTS_COLLECTION) + return mc.deleteById(id, db.EventsCollection) } // Get a list of events based on the device id and limit @@ -223,12 +216,12 @@ func (mc *MongoClient) ScrubAllEvents() error { s := mc.getSessionCopy() defer s.Close() - _, err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).RemoveAll(nil) + _, err := s.DB(mc.Database.Name).C(db.ReadingsCollection).RemoveAll(nil) if err != nil { return err } - _, err = s.DB(mc.Database.Name).C(EVENTS_COLLECTION).RemoveAll(nil) + _, err = s.DB(mc.Database.Name).C(db.EventsCollection).RemoveAll(nil) if err != nil { return err } @@ -244,7 +237,7 @@ func (mc *MongoClient) getEvents(q bson.M) ([]models.Event, error) { // Handle DBRefs var me []MongoEvent events := []models.Event{} - err := s.DB(mc.Database.Name).C(EVENTS_COLLECTION).Find(q).All(&me) + err := s.DB(mc.Database.Name).C(db.EventsCollection).Find(q).All(&me) if err != nil { return events, err } @@ -271,7 +264,7 @@ func (mc *MongoClient) getEventsLimit(q bson.M, limit int) ([]models.Event, erro return events, nil } - err := s.DB(mc.Database.Name).C(EVENTS_COLLECTION).Find(q).Limit(limit).All(&me) + err := s.DB(mc.Database.Name).C(db.EventsCollection).Find(q).Limit(limit).All(&me) if err != nil { return events, err } @@ -291,9 +284,9 @@ func (mc *MongoClient) getEvent(q bson.M) (models.Event, error) { // Handle DBRef var me MongoEvent - err := s.DB(mc.Database.Name).C(EVENTS_COLLECTION).Find(q).One(&me) + err := s.DB(mc.Database.Name).C(db.EventsCollection).Find(q).One(&me) if err == mgo.ErrNotFound { - return me.Event, ErrNotFound + return me.Event, db.ErrNotFound } return me.Event, err @@ -315,7 +308,7 @@ func (mc *MongoClient) AddReading(r models.Reading) (bson.ObjectId, error) { r.Id = bson.NewObjectId() r.Created = time.Now().UnixNano() / int64(time.Millisecond) - err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).Insert(&r) + err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Insert(&r) return r.Id, err } @@ -330,9 +323,9 @@ func (mc *MongoClient) UpdateReading(r models.Reading) error { r.Modified = time.Now().UnixNano() / int64(time.Millisecond) // Update the reading - err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).UpdateId(r.Id, r) + err := s.DB(mc.Database.Name).C(db.ReadingsCollection).UpdateId(r.Id, r) if err == mgo.ErrNotFound { - return ErrNotFound + return db.ErrNotFound } return err @@ -342,7 +335,7 @@ func (mc *MongoClient) UpdateReading(r models.Reading) error { func (mc *MongoClient) ReadingById(id string) (models.Reading, error) { // Check if the id is a id hex if !bson.IsObjectIdHex(id) { - return models.Reading{}, ErrInvalidObjectId + return models.Reading{}, db.ErrInvalidObjectId } query := bson.M{"_id": bson.ObjectIdHex(id)} @@ -355,7 +348,7 @@ func (mc *MongoClient) ReadingCount() (int, error) { s := mc.getSessionCopy() defer s.Close() - return s.DB(mc.Database.Name).C(READINGS_COLLECTION).Find(bson.M{}).Count() + return s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(bson.M{}).Count() } // Delete a reading by ID @@ -363,10 +356,10 @@ func (mc *MongoClient) ReadingCount() (int, error) { func (mc *MongoClient) DeleteReadingById(id string) error { // Check if the id is a bson id if !bson.IsObjectIdHex(id) { - return ErrInvalidObjectId + return db.ErrInvalidObjectId } - return mc.deleteById(id, READINGS_COLLECTION) + return mc.deleteById(id, db.ReadingsCollection) } // Return a list of readings for the given device (id or name) @@ -417,7 +410,7 @@ func (mc *MongoClient) getReadingsLimit(q bson.M, limit int) ([]models.Reading, return readings, nil } - err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).Find(q).Limit(limit).All(&readings) + err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(q).Limit(limit).All(&readings) return readings, err } @@ -427,7 +420,7 @@ func (mc *MongoClient) getReadings(q bson.M) ([]models.Reading, error) { defer s.Close() readings := []models.Reading{} - err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).Find(q).All(&readings) + err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(q).All(&readings) return readings, err } @@ -437,9 +430,9 @@ func (mc *MongoClient) getReading(q bson.M) (models.Reading, error) { defer s.Close() var res models.Reading - err := s.DB(mc.Database.Name).C(READINGS_COLLECTION).Find(q).One(&res) + err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(q).One(&res) if err == mgo.ErrNotFound { - return res, ErrNotFound + return res, db.ErrNotFound } return res, err } @@ -458,14 +451,14 @@ func (mc *MongoClient) AddValueDescriptor(v models.ValueDescriptor) (bson.Object v.Created = time.Now().UnixNano() / int64(time.Millisecond) // See if the name is unique and add the value descriptors - info, err := s.DB(mc.Database.Name).C(VALUE_DESCRIPTOR_COLLECTION).Upsert(bson.M{"name": v.Name}, v) + info, err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Upsert(bson.M{"name": v.Name}, v) if err != nil { return v.Id, err } // Duplicate name if info.UpsertedId == nil { - return v.Id, ErrNotUnique + return v.Id, db.ErrNotUnique } // Set ID @@ -490,22 +483,22 @@ func (mc *MongoClient) UpdateValueDescriptor(v models.ValueDescriptor) error { // See if the name is unique if it changed vd, err := mc.getValueDescriptor(bson.M{"name": v.Name}) - if err != ErrNotFound { + if err != db.ErrNotFound { if err != nil { return err } // IDs are different -> name not unique if vd.Id != v.Id { - return ErrNotUnique + return db.ErrNotUnique } } v.Modified = time.Now().UnixNano() / int64(time.Millisecond) - err = s.DB(mc.Database.Name).C(VALUE_DESCRIPTOR_COLLECTION).UpdateId(v.Id, v) + err = s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).UpdateId(v.Id, v) if err == mgo.ErrNotFound { - return ErrNotFound + return db.ErrNotFound } return err } @@ -515,9 +508,9 @@ func (mc *MongoClient) UpdateValueDescriptor(v models.ValueDescriptor) error { // ValueDescriptorStillInUse if the value descriptor is still referenced by readings func (mc *MongoClient) DeleteValueDescriptorById(id string) error { if !bson.IsObjectIdHex(id) { - return ErrInvalidObjectId + return db.ErrInvalidObjectId } - return mc.deleteById(id, VALUE_DESCRIPTOR_COLLECTION) + return mc.deleteById(id, db.ValueDescriptorCollection) } // Return a value descriptor based on the name @@ -533,7 +526,7 @@ func (mc *MongoClient) ValueDescriptorsByName(names []string) ([]models.ValueDes for _, name := range names { v, err := mc.ValueDescriptorByName(name) - if err != nil && err != ErrNotFound { + if err != nil && err != db.ErrNotFound { return []models.ValueDescriptor{}, err } if err == nil { @@ -548,7 +541,7 @@ func (mc *MongoClient) ValueDescriptorsByName(names []string) ([]models.ValueDes // Return NotFoundError if there is no value descriptor for the id func (mc *MongoClient) ValueDescriptorById(id string) (models.ValueDescriptor, error) { if !bson.IsObjectIdHex(id) { - return models.ValueDescriptor{}, ErrInvalidObjectId + return models.ValueDescriptor{}, db.ErrInvalidObjectId } query := bson.M{"_id": bson.ObjectIdHex(id)} @@ -578,7 +571,7 @@ func (mc *MongoClient) ScrubAllValueDescriptors() error { s := mc.getSessionCopy() defer s.Close() - _, err := s.DB(mc.Database.Name).C(VALUE_DESCRIPTOR_COLLECTION).RemoveAll(nil) + _, err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).RemoveAll(nil) if err != nil { return err } @@ -592,7 +585,7 @@ func (mc *MongoClient) getValueDescriptors(q bson.M) ([]models.ValueDescriptor, defer s.Close() v := []models.ValueDescriptor{} - err := s.DB(mc.Database.Name).C(VALUE_DESCRIPTOR_COLLECTION).Find(q).All(&v) + err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Find(q).All(&v) return v, err } @@ -603,7 +596,7 @@ func (mc *MongoClient) getValueDescriptorsLimit(q bson.M, limit int) ([]models.V defer s.Close() v := []models.ValueDescriptor{} - err := s.DB(mc.Database.Name).C(VALUE_DESCRIPTOR_COLLECTION).Find(q).Limit(limit).All(&v) + err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Find(q).Limit(limit).All(&v) return v, err } @@ -614,9 +607,9 @@ func (mc *MongoClient) getValueDescriptor(q bson.M) (models.ValueDescriptor, err defer s.Close() var v models.ValueDescriptor - err := s.DB(mc.Database.Name).C(VALUE_DESCRIPTOR_COLLECTION).Find(q).One(&v) + err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Find(q).One(&v) if err == mgo.ErrNotFound { - return v, ErrNotFound + return v, db.ErrNotFound } return v, err @@ -629,12 +622,12 @@ func (mc *MongoClient) deleteById(id string, col string) error { // Check if id is a hexstring if !bson.IsObjectIdHex(id) { - return ErrInvalidObjectId + return db.ErrInvalidObjectId } err := s.DB(mc.Database.Name).C(col).RemoveId(bson.ObjectIdHex(id)) if err == mgo.ErrNotFound { - return ErrNotFound + return db.ErrNotFound } return err } diff --git a/core/data/clients/mongo-client_test.go b/core/db/mongo/mongo-client_test.go similarity index 81% rename from core/data/clients/mongo-client_test.go rename to core/db/mongo/mongo-client_test.go index b09b0c90ac..f4991c344f 100644 --- a/core/data/clients/mongo-client_test.go +++ b/core/db/mongo/mongo-client_test.go @@ -10,30 +10,32 @@ // the tests with a command like: // go test -tags mongoRunning -package clients +package mongo import ( "testing" + + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/db/test" ) func TestMongoDB(t *testing.T) { t.Log("This test needs to have a running mongo on localhost") - config := DBConfiguration{ - DbType: MONGO, + config := db.Configuration{ Host: "0.0.0.0", Port: 27017, DatabaseName: "coredata", Timeout: 1000, } - mongo, err := newMongoClient(config) + mongo, err := NewClient(config) if err != nil { t.Fatalf("Could not connect with mongodb: %v", err) } - testDB(t, mongo) + test.TestDataDB(t, mongo) } func BenchmarkMongoDB(b *testing.B) { diff --git a/core/data/clients/MongoEvent.go b/core/db/mongo/mongoevent.go similarity index 92% rename from core/data/clients/MongoEvent.go rename to core/db/mongo/mongoevent.go index 8c40c5ec7f..e4dc649937 100644 --- a/core/data/clients/MongoEvent.go +++ b/core/db/mongo/mongoevent.go @@ -11,9 +11,10 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package clients +package mongo import ( + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -29,7 +30,7 @@ func (me MongoEvent) GetBSON() (interface{}, error) { // Turn the readings into DBRef objects var readings []mgo.DBRef for _, reading := range me.Readings { - readings = append(readings, mgo.DBRef{Collection: READINGS_COLLECTION, Id: reading.Id}) + readings = append(readings, mgo.DBRef{Collection: db.ReadingsCollection, Id: reading.Id}) } return struct { @@ -85,7 +86,6 @@ func (me *MongoEvent) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields mc, err := getCurrentMongoClient() if err != nil { - loggingClient.Error("Error getting a mongo client: " + err.Error()) return err } @@ -94,7 +94,7 @@ func (me *MongoEvent) SetBSON(raw bson.Raw) error { // Get all of the reading objects for _, rRef := range decoded.Readings { var reading models.Reading - err := mc.Database.C(READINGS_COLLECTION).FindId(rRef.Id).One(&reading) + err := mc.Database.C(db.ReadingsCollection).FindId(rRef.Id).One(&reading) if err != nil { return err } diff --git a/core/data/clients/memory-database_test.go b/core/db/test/db.go similarity index 97% rename from core/data/clients/memory-database_test.go rename to core/db/test/db.go index 75f7522272..870ffe17fb 100644 --- a/core/data/clients/memory-database_test.go +++ b/core/db/test/db.go @@ -4,7 +4,7 @@ // SPDX-License-Identifier: Apache-2.0 // -package clients +package test import ( "fmt" @@ -12,11 +12,12 @@ import ( "testing" "time" + "github.com/edgexfoundry/edgex-go/core/data/clients" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2/bson" ) -func populateDbReadings(db DBClient, count int) (bson.ObjectId, error) { +func populateDbReadings(db clients.DBClient, count int) (bson.ObjectId, error) { var id bson.ObjectId for i := 0; i < count; i++ { name := fmt.Sprintf("name%d", i) @@ -33,7 +34,7 @@ func populateDbReadings(db DBClient, count int) (bson.ObjectId, error) { return id, nil } -func populateDbValues(db DBClient, count int) (bson.ObjectId, error) { +func populateDbValues(db clients.DBClient, count int) (bson.ObjectId, error) { var id bson.ObjectId for i := 0; i < count; i++ { name := fmt.Sprintf("name%d", i) @@ -52,7 +53,7 @@ func populateDbValues(db DBClient, count int) (bson.ObjectId, error) { return id, nil } -func populateDbEvents(db DBClient, count int, pushed int64) (bson.ObjectId, error) { +func populateDbEvents(db clients.DBClient, count int, pushed int64) (bson.ObjectId, error) { var id bson.ObjectId for i := 0; i < count; i++ { name := fmt.Sprintf("name%d", i) @@ -69,7 +70,7 @@ func populateDbEvents(db DBClient, count int, pushed int64) (bson.ObjectId, erro return id, nil } -func testDBReadings(t *testing.T, db DBClient) { +func testDBReadings(t *testing.T, db clients.DBClient) { err := db.ScrubAllEvents() if err != nil { t.Fatalf("Error removing all readings") @@ -263,7 +264,7 @@ func testDBReadings(t *testing.T, db DBClient) { } } -func testDBEvents(t *testing.T, db DBClient) { +func testDBEvents(t *testing.T, db clients.DBClient) { err := db.ScrubAllEvents() if err != nil { t.Fatalf("Error removing all events") @@ -466,7 +467,7 @@ func testDBEvents(t *testing.T, db DBClient) { } } -func testDBValueDescriptors(t *testing.T, db DBClient) { +func testDBValueDescriptors(t *testing.T, db clients.DBClient) { err := db.ScrubAllValueDescriptors() if err != nil { t.Fatalf("Error removing all value descriptors") @@ -617,7 +618,7 @@ func testDBValueDescriptors(t *testing.T, db DBClient) { } } -func testDB(t *testing.T, db DBClient) { +func TestDataDB(t *testing.T, db clients.DBClient) { testDBReadings(t, db) testDBEvents(t, db) testDBValueDescriptors(t, db) From 424c3ee08e525bd395175a676ed091bbc7eeb5f1 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Wed, 6 Jun 2018 15:05:57 +0200 Subject: [PATCH 04/10] Moving the mongo database from metadata to core/db Signed-off-by: Federico Claramonte --- core/data/clients/database-client.go | 3 +- core/data/init.go | 15 +- core/db/db.go | 23 +- core/db/influx/influx-client.go | 4 + core/db/memory/memory-database.go | 4 + core/db/mongo/mongo-client.go | 88 +- core/db/mongo/mongo-client_test.go | 6 +- core/db/mongo/mongoOps.go | 1025 ++++++++++++++++ core/{metadata => db/mongo}/mongo_device.go | 26 +- .../mongo}/mongo_deviceprofile.go | 17 +- .../mongo}/mongo_deviceservice.go | 18 +- .../mongo}/mongo_provisionwatcher.go | 20 +- .../mongo}/mongo_scheduleevent.go | 16 +- core/db/mongo/mongoevent.go | 2 +- core/db/test/db.go | 7 + core/metadata/const.go | 38 +- core/metadata/dbOps.go | 162 +-- core/metadata/init.go | 32 +- core/metadata/mongoOps.go | 1050 ----------------- core/metadata/rest_addressable.go | 39 +- core/metadata/rest_command.go | 25 +- core/metadata/rest_device.go | 123 +- core/metadata/rest_deviceprofile.go | 51 +- core/metadata/rest_devicereport.go | 39 +- core/metadata/rest_deviceservice.go | 77 +- core/metadata/rest_provisionwatcher.go | 53 +- core/metadata/rest_scheduleevent.go | 85 +- 27 files changed, 1505 insertions(+), 1543 deletions(-) create mode 100644 core/db/mongo/mongoOps.go rename core/{metadata => db/mongo}/mongo_device.go (89%) rename core/{metadata => db/mongo}/mongo_deviceprofile.go (95%) rename core/{metadata => db/mongo}/mongo_deviceservice.go (92%) rename core/{metadata => db/mongo}/mongo_provisionwatcher.go (89%) rename core/{metadata => db/mongo}/mongo_scheduleevent.go (91%) delete mode 100644 core/metadata/mongoOps.go diff --git a/core/data/clients/database-client.go b/core/data/clients/database-client.go index 2ca960c3d8..f1db9496c7 100644 --- a/core/data/clients/database-client.go +++ b/core/data/clients/database-client.go @@ -28,6 +28,8 @@ const ( type DBClient interface { CloseSession() + Connect() error + // ********************** EVENT FUNCTIONS ******************************* // Return all the events // UnexpectedError - failed to retrieve events from the database @@ -189,4 +191,3 @@ type DBClient interface { // Delete all value descriptors ScrubAllValueDescriptors() error } - diff --git a/core/data/init.go b/core/data/init.go index 484835359e..331a5b5287 100644 --- a/core/data/init.go +++ b/core/data/init.go @@ -66,12 +66,7 @@ func newDBClient(dbType clients.DatabaseType, config db.Configuration) (clients. switch dbType { case clients.MONGO: // Create the mongo client - mc, err := mongo.NewClient(config) - if err != nil { - loggingClient.Error("Error creating the mongo client: " + err.Error()) - return nil, err - } - return mc, nil + return mongo.NewClient(config), nil case clients.INFLUX: // Create the influx client ic, err := influx.NewClient(config) @@ -82,8 +77,7 @@ func newDBClient(dbType clients.DatabaseType, config db.Configuration) (clients. return ic, nil case clients.MEMORY: // Create the memory client - mem := &memory.MemDB{} - return mem, nil + return &memory.MemDB{}, nil default: return nil, db.ErrUnsupportedDatabase } @@ -105,6 +99,11 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient, useConsul bool) erro Username: conf.MongoDBUserName, Password: conf.MongoDBPassword, }) + if err != nil { + return fmt.Errorf("couldn't create database client: %v", err.Error()) + } + + err = dbc.Connect() if err != nil { return fmt.Errorf("couldn't connect to database: %v", err.Error()) } diff --git a/core/db/db.go b/core/db/db.go index 88ce61b9b0..e5cf9c5eae 100644 --- a/core/db/db.go +++ b/core/db/db.go @@ -17,15 +17,30 @@ package db import "errors" const ( + // Data EventsCollection = "event" ReadingsCollection = "reading" ValueDescriptorCollection = "valueDescriptor" + + // Metadata + Device = "device" + DeviceProfile = "deviceProfile" + DeviceService = "deviceService" + Addressable = "addressable" + Command = "command" + DeviceReport = "deviceReport" + ScheduleEvent = "scheduleEvent" + Schedule = "schedule" + ProvisionWatcher = "provisionWatcher" ) -var ErrNotFound error = errors.New("Item not found") -var ErrUnsupportedDatabase error = errors.New("Unsuppored database type") -var ErrInvalidObjectId error = errors.New("Invalid object ID") -var ErrNotUnique error = errors.New("Resource already exists") +var ( + ErrNotFound = errors.New("Item not found") + ErrUnsupportedDatabase = errors.New("Unsuppored database type") + ErrInvalidObjectId = errors.New("Invalid object ID") + ErrNotUnique = errors.New("Resource already exists") + ErrCommandStillInUse = errors.New("Command is still in use by device profiles") +) type Configuration struct { Host string diff --git a/core/db/influx/influx-client.go b/core/db/influx/influx-client.go index 4f2f9299ca..ee8d6a1b3d 100644 --- a/core/db/influx/influx-client.go +++ b/core/db/influx/influx-client.go @@ -59,6 +59,10 @@ func NewClient(config db.Configuration) (*InfluxClient, error) { return influxClient, nil } +func (ic *InfluxClient) Connect() error { + return nil +} + // Perform an Influxdb query func (ic *InfluxClient) queryDB(cmd string) (res []client.Result, err error) { q := client.Query{ diff --git a/core/db/memory/memory-database.go b/core/db/memory/memory-database.go index cdd3edc0ce..2eb4de4fb1 100644 --- a/core/db/memory/memory-database.go +++ b/core/db/memory/memory-database.go @@ -30,6 +30,10 @@ type MemDB struct { func (m *MemDB) CloseSession() { } +func (m *MemDB) Connect() error { + return nil +} + func (m *MemDB) AddReading(r models.Reading) (bson.ObjectId, error) { currentTime := time.Now().UnixNano() / int64(time.Millisecond) r.Created = currentTime diff --git a/core/db/mongo/mongo-client.go b/core/db/mongo/mongo-client.go index 13fb8bc88a..ff567cf923 100644 --- a/core/db/mongo/mongo-client.go +++ b/core/db/mongo/mongo-client.go @@ -15,7 +15,6 @@ package mongo import ( "errors" - "strconv" "time" "github.com/edgexfoundry/edgex-go/core/db" @@ -39,29 +38,16 @@ func (a ByReadingCreationDate) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByReadingCreationDate) Less(i, j int) bool { return (a[i].Created < a[j].Created) } type MongoClient struct { - Session *mgo.Session // Mongo database session - Database *mgo.Database // Mongo database + config db.Configuration + session *mgo.Session // Mongo database session + database *mgo.Database // Mongo database } // Return a pointer to the MongoClient -func NewClient(config db.Configuration) (*MongoClient, error) { - // Create the dial info for the Mongo session - connectionString := config.Host + ":" + strconv.Itoa(config.Port) - mongoDBDialInfo := &mgo.DialInfo{ - Addrs: []string{connectionString}, - Timeout: time.Duration(config.Timeout) * time.Millisecond, - Database: config.DatabaseName, - Username: config.Username, - Password: config.Password, - } - session, err := mgo.DialWithInfo(mongoDBDialInfo) - if err != nil { - return nil, err - } - - mongoClient := &MongoClient{Session: session, Database: session.DB(config.DatabaseName)} +func NewClient(config db.Configuration) *MongoClient { + mongoClient := &MongoClient{config: config} currentMongoClient = mongoClient // Set the singleton - return mongoClient, nil + return mongoClient } // Get the current Mongo Client @@ -75,11 +61,7 @@ func getCurrentMongoClient() (*MongoClient, error) { // Get a copy of the session func (mc *MongoClient) getSessionCopy() *mgo.Session { - return mc.Session.Copy() -} - -func (mc *MongoClient) CloseSession() { - mc.Session.Close() + return mc.session.Copy() } // ******************************* EVENTS ********************************** @@ -140,7 +122,7 @@ func (mc *MongoClient) UpdateEvent(e models.Event) error { // Handle DBRef me := MongoEvent{Event: e} - err := s.DB(mc.Database.Name).C(db.EventsCollection).UpdateId(me.ID, me) + err := s.DB(mc.database.Name).C(db.EventsCollection).UpdateId(me.ID, me) if err == mgo.ErrNotFound { return db.ErrNotFound } @@ -161,7 +143,7 @@ func (mc *MongoClient) EventCount() (int, error) { s := mc.getSessionCopy() defer s.Close() - return s.DB(mc.Database.Name).C(db.EventsCollection).Find(nil).Count() + return s.DB(mc.database.Name).C(db.EventsCollection).Find(nil).Count() } // Get the number of events in Mongo for the device @@ -170,14 +152,14 @@ func (mc *MongoClient) EventCountByDeviceId(id string) (int, error) { defer s.Close() query := bson.M{"device": id} - return s.DB(mc.Database.Name).C(db.EventsCollection).Find(query).Count() + return s.DB(mc.database.Name).C(db.EventsCollection).Find(query).Count() } // Delete an event by ID and all of its readings // 404 - Event not found // 503 - Unexpected problems func (mc *MongoClient) DeleteEventById(id string) error { - return mc.deleteById(id, db.EventsCollection) + return mc.deleteById(db.EventsCollection, id) } // Get a list of events based on the device id and limit @@ -216,12 +198,12 @@ func (mc *MongoClient) ScrubAllEvents() error { s := mc.getSessionCopy() defer s.Close() - _, err := s.DB(mc.Database.Name).C(db.ReadingsCollection).RemoveAll(nil) + _, err := s.DB(mc.database.Name).C(db.ReadingsCollection).RemoveAll(nil) if err != nil { return err } - _, err = s.DB(mc.Database.Name).C(db.EventsCollection).RemoveAll(nil) + _, err = s.DB(mc.database.Name).C(db.EventsCollection).RemoveAll(nil) if err != nil { return err } @@ -237,7 +219,7 @@ func (mc *MongoClient) getEvents(q bson.M) ([]models.Event, error) { // Handle DBRefs var me []MongoEvent events := []models.Event{} - err := s.DB(mc.Database.Name).C(db.EventsCollection).Find(q).All(&me) + err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).All(&me) if err != nil { return events, err } @@ -264,7 +246,7 @@ func (mc *MongoClient) getEventsLimit(q bson.M, limit int) ([]models.Event, erro return events, nil } - err := s.DB(mc.Database.Name).C(db.EventsCollection).Find(q).Limit(limit).All(&me) + err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).Limit(limit).All(&me) if err != nil { return events, err } @@ -284,7 +266,7 @@ func (mc *MongoClient) getEvent(q bson.M) (models.Event, error) { // Handle DBRef var me MongoEvent - err := s.DB(mc.Database.Name).C(db.EventsCollection).Find(q).One(&me) + err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).One(&me) if err == mgo.ErrNotFound { return me.Event, db.ErrNotFound } @@ -308,7 +290,7 @@ func (mc *MongoClient) AddReading(r models.Reading) (bson.ObjectId, error) { r.Id = bson.NewObjectId() r.Created = time.Now().UnixNano() / int64(time.Millisecond) - err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Insert(&r) + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(&r) return r.Id, err } @@ -323,7 +305,7 @@ func (mc *MongoClient) UpdateReading(r models.Reading) error { r.Modified = time.Now().UnixNano() / int64(time.Millisecond) // Update the reading - err := s.DB(mc.Database.Name).C(db.ReadingsCollection).UpdateId(r.Id, r) + err := s.DB(mc.database.Name).C(db.ReadingsCollection).UpdateId(r.Id, r) if err == mgo.ErrNotFound { return db.ErrNotFound } @@ -348,7 +330,7 @@ func (mc *MongoClient) ReadingCount() (int, error) { s := mc.getSessionCopy() defer s.Close() - return s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(bson.M{}).Count() + return s.DB(mc.database.Name).C(db.ReadingsCollection).Find(bson.M{}).Count() } // Delete a reading by ID @@ -359,7 +341,7 @@ func (mc *MongoClient) DeleteReadingById(id string) error { return db.ErrInvalidObjectId } - return mc.deleteById(id, db.ReadingsCollection) + return mc.deleteById(db.ReadingsCollection, id) } // Return a list of readings for the given device (id or name) @@ -410,7 +392,7 @@ func (mc *MongoClient) getReadingsLimit(q bson.M, limit int) ([]models.Reading, return readings, nil } - err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(q).Limit(limit).All(&readings) + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).Limit(limit).All(&readings) return readings, err } @@ -420,7 +402,7 @@ func (mc *MongoClient) getReadings(q bson.M) ([]models.Reading, error) { defer s.Close() readings := []models.Reading{} - err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(q).All(&readings) + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).All(&readings) return readings, err } @@ -430,7 +412,7 @@ func (mc *MongoClient) getReading(q bson.M) (models.Reading, error) { defer s.Close() var res models.Reading - err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Find(q).One(&res) + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).One(&res) if err == mgo.ErrNotFound { return res, db.ErrNotFound } @@ -451,7 +433,7 @@ func (mc *MongoClient) AddValueDescriptor(v models.ValueDescriptor) (bson.Object v.Created = time.Now().UnixNano() / int64(time.Millisecond) // See if the name is unique and add the value descriptors - info, err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Upsert(bson.M{"name": v.Name}, v) + info, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Upsert(bson.M{"name": v.Name}, v) if err != nil { return v.Id, err } @@ -496,7 +478,7 @@ func (mc *MongoClient) UpdateValueDescriptor(v models.ValueDescriptor) error { v.Modified = time.Now().UnixNano() / int64(time.Millisecond) - err = s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).UpdateId(v.Id, v) + err = s.DB(mc.database.Name).C(db.ValueDescriptorCollection).UpdateId(v.Id, v) if err == mgo.ErrNotFound { return db.ErrNotFound } @@ -510,7 +492,7 @@ func (mc *MongoClient) DeleteValueDescriptorById(id string) error { if !bson.IsObjectIdHex(id) { return db.ErrInvalidObjectId } - return mc.deleteById(id, db.ValueDescriptorCollection) + return mc.deleteById(db.ValueDescriptorCollection, id) } // Return a value descriptor based on the name @@ -571,7 +553,7 @@ func (mc *MongoClient) ScrubAllValueDescriptors() error { s := mc.getSessionCopy() defer s.Close() - _, err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).RemoveAll(nil) + _, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).RemoveAll(nil) if err != nil { return err } @@ -585,7 +567,7 @@ func (mc *MongoClient) getValueDescriptors(q bson.M) ([]models.ValueDescriptor, defer s.Close() v := []models.ValueDescriptor{} - err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Find(q).All(&v) + err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).All(&v) return v, err } @@ -596,7 +578,7 @@ func (mc *MongoClient) getValueDescriptorsLimit(q bson.M, limit int) ([]models.V defer s.Close() v := []models.ValueDescriptor{} - err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Find(q).Limit(limit).All(&v) + err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).Limit(limit).All(&v) return v, err } @@ -607,7 +589,7 @@ func (mc *MongoClient) getValueDescriptor(q bson.M) (models.ValueDescriptor, err defer s.Close() var v models.ValueDescriptor - err := s.DB(mc.Database.Name).C(db.ValueDescriptorCollection).Find(q).One(&v) + err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).One(&v) if err == mgo.ErrNotFound { return v, db.ErrNotFound } @@ -616,16 +598,16 @@ func (mc *MongoClient) getValueDescriptor(q bson.M) (models.ValueDescriptor, err } // Delete from the collection based on ID -func (mc *MongoClient) deleteById(id string, col string) error { - s := mc.getSessionCopy() - defer s.Close() - +func (mc *MongoClient) deleteById(col string, id string) error { // Check if id is a hexstring if !bson.IsObjectIdHex(id) { return db.ErrInvalidObjectId } - err := s.DB(mc.Database.Name).C(col).RemoveId(bson.ObjectIdHex(id)) + s := mc.getSessionCopy() + defer s.Close() + + err := s.DB(mc.database.Name).C(col).RemoveId(bson.ObjectIdHex(id)) if err == mgo.ErrNotFound { return db.ErrNotFound } diff --git a/core/db/mongo/mongo-client_test.go b/core/db/mongo/mongo-client_test.go index f4991c344f..eaef5f96d3 100644 --- a/core/db/mongo/mongo-client_test.go +++ b/core/db/mongo/mongo-client_test.go @@ -30,11 +30,7 @@ func TestMongoDB(t *testing.T) { Timeout: 1000, } - mongo, err := NewClient(config) - if err != nil { - t.Fatalf("Could not connect with mongodb: %v", err) - } - + mongo := NewClient(config) test.TestDataDB(t, mongo) } diff --git a/core/db/mongo/mongoOps.go b/core/db/mongo/mongoOps.go new file mode 100644 index 0000000000..9bada3fbd7 --- /dev/null +++ b/core/db/mongo/mongoOps.go @@ -0,0 +1,1025 @@ +/******************************************************************************* + * Copyright 2017 Dell Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ +package mongo + +import ( + "errors" + "strconv" + "time" + + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/domain/models" + "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" +) + +func makeTimestamp() int64 { + return time.Now().UnixNano() / int64(time.Millisecond) +} + +func (m *MongoClient) Connect() error { + // Create the dial info for the Mongo session + connectionString := m.config.Host + ":" + strconv.Itoa(m.config.Port) + mongoDBDialInfo := &mgo.DialInfo{ + Addrs: []string{connectionString}, + Timeout: time.Duration(m.config.Timeout) * time.Millisecond, + Database: m.config.DatabaseName, + Username: m.config.Username, + Password: m.config.Password, + } + session, err := mgo.DialWithInfo(mongoDBDialInfo) + if err != nil { + return err + } + + m.session = session + m.database = session.DB(m.config.DatabaseName) + currentMongoClient = m // Set the singleton + + return nil +} + +func (m *MongoClient) CloseSession() { + if m.session != nil { + m.session.Close() + m.session = nil + } +} + +/* -----------------------Schedule Event ------------------------*/ +func (m *MongoClient) UpdateScheduleEvent(se models.ScheduleEvent) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ScheduleEvent) + + se.Modified = makeTimestamp() + + // Handle DBRefs + mse := MongoScheduleEvent{ScheduleEvent: se} + + return col.UpdateId(se.Id, mse) +} + +func (m *MongoClient) AddScheduleEvent(se *models.ScheduleEvent) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ScheduleEvent) + count, err := col.Find(bson.M{"name": se.Name}).Count() + if err != nil { + return err + } else if count > 0 { + return db.ErrNotUnique + } + ts := makeTimestamp() + se.Created = ts + se.Modified = ts + se.Id = bson.NewObjectId() + + // Handle DBRefs + mse := MongoScheduleEvent{ScheduleEvent: *se} + + return col.Insert(mse) +} + +func (m *MongoClient) GetAllScheduleEvents(se *[]models.ScheduleEvent) error { + return m.GetScheduleEvents(se, bson.M{}) +} + +func (m *MongoClient) GetScheduleEventByName(se *models.ScheduleEvent, n string) error { + return m.GetScheduleEvent(se, bson.M{"name": n}) +} + +func (m *MongoClient) GetScheduleEventById(se *models.ScheduleEvent, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetScheduleEvent(se, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetScheduleEventById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error { + return m.GetScheduleEvents(se, bson.M{"schedule": n}) +} + +func (m *MongoClient) GetScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetScheduleEvents(se, bson.M{"addressable" + ".$id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetScheduleEventsByAddressableId Invalid Object ID" + id) + return err + } +} + +func (m *MongoClient) GetScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error { + return m.GetScheduleEvents(se, bson.M{"service": n}) +} + +func (m *MongoClient) GetScheduleEvent(se *models.ScheduleEvent, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ScheduleEvent) + + // Handle DBRef + var mse MongoScheduleEvent + + err := col.Find(q).One(&mse) + if err != nil { + return err + } + + *se = mse.ScheduleEvent + + return err +} + +func (m *MongoClient) GetScheduleEvents(se *[]models.ScheduleEvent, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ScheduleEvent) + + // Handle the DBRef + var mses []MongoScheduleEvent + + err := col.Find(q).Sort("queryts").All(&mses) + if err != nil { + return err + } + + for _, mse := range mses { + *se = append(*se, mse.ScheduleEvent) + } + + return nil +} + +func (m *MongoClient) DeleteScheduleEvent(se models.ScheduleEvent) error { + return m.deleteById(db.ScheduleEvent, se.Id.Hex()) +} + +// --------------------------Schedule ---------------------------*/ +func (m *MongoClient) GetAllSchedules(s *[]models.Schedule) error { + return m.GetSchedules(s, bson.M{}) +} + +func (m *MongoClient) GetScheduleByName(s *models.Schedule, n string) error { + return m.GetSchedule(s, bson.M{"name": n}) +} + +func (m *MongoClient) GetScheduleById(s *models.Schedule, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetSchedule(s, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetScheduleById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) AddSchedule(sch *models.Schedule) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Schedule) + count, err := col.Find(bson.M{"name": sch.Name}).Count() + if err != nil { + return err + } else if count > 0 { + err := errors.New("Schedule already exist") + return err + } + + ts := makeTimestamp() + sch.Created = ts + sch.Modified = ts + sch.Id = bson.NewObjectId() + return col.Insert(s) +} + +func (m *MongoClient) UpdateSchedule(sch models.Schedule) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Schedule) + + sch.Modified = makeTimestamp() + + if err := col.UpdateId(sch.Id, sch); err != nil { + return err + } + + return nil +} + +func (m *MongoClient) DeleteSchedule(s models.Schedule) error { + return m.deleteById(db.Schedule, s.Id.Hex()) +} + +func (m *MongoClient) GetSchedule(sch *models.Schedule, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Schedule) + return col.Find(q).One(sch) +} + +func (m *MongoClient) GetSchedules(sch *[]models.Schedule, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Schedule) + return col.Find(q).Sort("queryts").All(sch) +} + +/* ----------------------Device Report --------------------------*/ +func (m *MongoClient) GetAllDeviceReports(d *[]models.DeviceReport) error { + return m.GetDeviceReports(d, bson.M{}) +} + +func (m *MongoClient) GetDeviceReportByName(d *models.DeviceReport, n string) error { + return m.GetDeviceReport(d, bson.M{"name": n}) +} + +func (m *MongoClient) GetDeviceReportByDeviceName(d *[]models.DeviceReport, n string) error { + return m.GetDeviceReports(d, bson.M{"device": n}) +} + +func (m *MongoClient) GetDeviceReportById(d *models.DeviceReport, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetDeviceReport(d, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetDeviceReportById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetDeviceReportsByScheduleEventName(d *[]models.DeviceReport, n string) error { + return m.GetDeviceReports(d, bson.M{"event": n}) +} + +func (m *MongoClient) GetDeviceReports(d *[]models.DeviceReport, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceReport) + return col.Find(q).Sort("queryts").All(d) +} + +func (m *MongoClient) GetDeviceReport(d *models.DeviceReport, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceReport) + return col.Find(q).One(d) +} + +func (m *MongoClient) AddDeviceReport(d *models.DeviceReport) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceReport) + count, err := col.Find(bson.M{"name": d.Name}).Count() + if err != nil { + return err + } else if count > 0 { + return db.ErrNotUnique + } + ts := makeTimestamp() + d.Created = ts + d.Id = bson.NewObjectId() + return col.Insert(d) +} + +func (m *MongoClient) UpdateDeviceReport(dr *models.DeviceReport) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceReport) + + return col.UpdateId(dr.Id, dr) +} + +func (m *MongoClient) DeleteDeviceReport(dr models.DeviceReport) error { + return m.deleteById(db.DeviceReport, dr.Id.Hex()) +} + +/* ----------------------------- Device ---------------------------------- */ +func (m *MongoClient) AddDevice(d *models.Device) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Device) + + // Check if the name exist (Device names must be unique) + count, err := col.Find(bson.M{"name": d.Name}).Count() + if err != nil { + return err + } + if count > 0 { + return db.ErrNotUnique + } + ts := makeTimestamp() + d.Created = ts + d.Modified = ts + d.Id = bson.NewObjectId() + + // Wrap the device in MongoDevice (For DBRefs) + md := MongoDevice{Device: *d} + + return col.Insert(md) +} + +func (m *MongoClient) UpdateDevice(rd models.Device) error { + s := m.session.Copy() + defer s.Close() + c := s.DB(m.database.Name).C(db.Device) + + // Copy over the DBRefs + md := MongoDevice{Device: rd} + + return c.UpdateId(rd.Id, md) +} + +func (m *MongoClient) DeleteDevice(d models.Device) error { + return m.deleteById(db.Device, d.Id.Hex()) +} + +func (m *MongoClient) GetAllDevices(d *[]models.Device) error { + return m.GetDevices(d, nil) +} + +func (m *MongoClient) GetDevicesByProfileId(d *[]models.Device, pid string) error { + if bson.IsObjectIdHex(pid) { + return m.GetDevices(d, bson.M{"profile.$id": bson.ObjectIdHex(pid)}) + } else { + err := errors.New("mgoGetDevicesByProfileId Invalid Object ID " + pid) + return err + } +} + +func (m *MongoClient) GetDeviceById(d *models.Device, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetDevice(d, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetDeviceById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetDeviceByName(d *models.Device, n string) error { + return m.GetDevice(d, bson.M{"name": n}) +} + +func (m *MongoClient) GetDevicesByServiceId(d *[]models.Device, sid string) error { + if bson.IsObjectIdHex(sid) { + return m.GetDevices(d, bson.M{"service.$id": bson.ObjectIdHex(sid)}) + } else { + err := errors.New("mgoGetDevicesByServiceId Invalid Object ID " + sid) + return err + } +} + +func (m *MongoClient) GetDevicesByAddressableId(d *[]models.Device, aid string) error { + if bson.IsObjectIdHex(aid) { + // Check if the addressable exists + var a *models.Addressable + if m.GetAddressableById(a, aid) == mgo.ErrNotFound { + return mgo.ErrNotFound + } + return m.GetDevices(d, bson.M{"addressable.$id": bson.ObjectIdHex(aid)}) + } else { + err := errors.New("mgoGetDevicesByAddressableId Invalid Object ID " + aid) + return err + } +} + +func (m *MongoClient) GetDevicesWithLabel(d *[]models.Device, l []string) error { + return m.GetDevices(d, bson.M{"labels": bson.M{"$in": l}}) +} + +func (m *MongoClient) GetDevices(d *[]models.Device, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Device) + mds := []MongoDevice{} + + err := col.Find(q).Sort("queryts").All(&mds) + if err != nil { + return err + } + + for _, md := range mds { + *d = append(*d, md.Device) + } + + return nil +} + +func (m *MongoClient) GetDevice(d *models.Device, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Device) + md := MongoDevice{} + + err := col.Find(q).One(&md) + if err != nil { + return err + } + + *d = md.Device + + return nil +} + +/* -----------------------------Device Profile -----------------------------*/ +func (m *MongoClient) GetDeviceProfileById(d *models.DeviceProfile, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetDeviceProfile(d, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetDeviceProfileById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetAllDeviceProfiles(dp *[]models.DeviceProfile) error { + return m.GetDeviceProfiles(dp, nil) +} + +func (m *MongoClient) GetDeviceProfilesByModel(dp *[]models.DeviceProfile, model string) error { + return m.GetDeviceProfiles(dp, bson.M{"model": model}) +} + +func (m *MongoClient) GetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error { + return m.GetDeviceProfiles(dp, bson.M{"labels": bson.M{"$in": l}}) +} +func (m *MongoClient) GetDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error { + return m.GetDeviceProfiles(dp, bson.M{"manufacturer": man, "model": mod}) +} +func (m *MongoClient) GetDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error { + return m.GetDeviceProfiles(dp, bson.M{"manufacturer": man}) +} +func (m *MongoClient) GetDeviceProfileByName(dp *models.DeviceProfile, n string) error { + return m.GetDeviceProfile(dp, bson.M{"name": n}) +} + +// Get device profiles with the passed query +func (m *MongoClient) GetDeviceProfiles(d *[]models.DeviceProfile, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceProfile) + + // Handle the DBRefs + var mdps []MongoDeviceProfile + err := col.Find(q).Sort("queryts").All(&mdps) + if err != nil { + return err + } + + for _, mdp := range mdps { + *d = append(*d, mdp.DeviceProfile) + } + + return err +} + +// Get device profile with the passed query +func (m *MongoClient) GetDeviceProfile(d *models.DeviceProfile, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceProfile) + + // Handle the DBRefs + var mdp MongoDeviceProfile + err := col.Find(q).One(&mdp) + if err != nil { + return err + } + + *d = mdp.DeviceProfile + + return err +} + +func (m *MongoClient) AddDeviceProfile(dp *models.DeviceProfile) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceProfile) + count, err := col.Find(bson.M{"name": dp.Name}).Count() + if err != nil { + return err + } else if count > 0 { + return db.ErrNotUnique + } + for i := 0; i < len(dp.Commands); i++ { + if err := m.AddCommand(&dp.Commands[i]); err != nil { + return err + } + } + ts := makeTimestamp() + dp.Created = ts + dp.Modified = ts + dp.Id = bson.NewObjectId() + + mdp := MongoDeviceProfile{DeviceProfile: *dp} + + return col.Insert(mdp) +} + +func (m *MongoClient) UpdateDeviceProfile(dp *models.DeviceProfile) error { + s := m.session.Copy() + defer s.Close() + c := s.DB(m.database.Name).C(db.DeviceProfile) + + mdp := MongoDeviceProfile{DeviceProfile: *dp} + mdp.Modified = makeTimestamp() + + return c.UpdateId(mdp.Id, mdp) +} + +// Get the device profiles that are currently using the command +func (m *MongoClient) GetDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error { + query := bson.M{"commands": bson.M{"$elemMatch": bson.M{"$id": c.Id}}} + return m.GetDeviceProfiles(dp, query) +} + +func (m *MongoClient) DeleteDeviceProfile(dp models.DeviceProfile) error { + return m.deleteById(db.DeviceProfile, dp.Id.Hex()) +} + +// -----------------------------------Addressable --------------------------*/ +func (m *MongoClient) UpdateAddressable(ra *models.Addressable, r *models.Addressable) error { + s := m.session.Copy() + + defer s.Close() + c := s.DB(m.database.Name).C(db.Addressable) + if ra == nil { + return nil + } + if ra.Name != "" { + r.Name = ra.Name + } + if ra.Protocol != "" { + r.Protocol = ra.Protocol + } + if ra.Address != "" { + r.Address = ra.Address + } + if ra.Port != int(0) { + r.Port = ra.Port + } + if ra.Path != "" { + r.Path = ra.Path + } + if ra.Publisher != "" { + r.Publisher = ra.Publisher + } + if ra.User != "" { + r.User = ra.User + } + if ra.Password != "" { + r.Password = ra.Password + } + if ra.Topic != "" { + r.Topic = ra.Topic + } + if err := c.UpdateId(r.Id, r); err != nil { + return err + } + return nil +} + +func (m *MongoClient) GetAddressables(d *[]models.Addressable) error { + return m.GetAddressablesQuery(d, bson.M{}) +} + +func (m *MongoClient) GetAddressablesQuery(d *[]models.Addressable, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Addressable) + err := col.Find(q).Sort("queryts").All(d) + if err != nil { + return err + } + + return nil +} + +func (m *MongoClient) GetAddressableById(a *models.Addressable, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetAddressable(a, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetAddressableById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) AddAddressable(a *models.Addressable) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Addressable) + + // check if the name exist + count, err := col.Find(bson.M{"name": a.Name}).Count() + if err != nil { + return err + } else if count > 0 { + return db.ErrNotUnique + } + + ts := makeTimestamp() + a.Created = ts + a.Id = bson.NewObjectId() + err = col.Insert(a) + if err != nil { + return err + } + + return nil +} + +func (m *MongoClient) GetAddressableByName(a *models.Addressable, n string) error { + return m.GetAddressable(a, bson.M{"name": n}) +} + +func (m *MongoClient) GetAddressablesByTopic(a *[]models.Addressable, t string) error { + return m.GetAddressablesQuery(a, bson.M{"topic": t}) +} + +func (m *MongoClient) GetAddressablesByPort(a *[]models.Addressable, p int) error { + return m.GetAddressablesQuery(a, bson.M{"port": p}) +} + +func (m *MongoClient) GetAddressablesByPublisher(a *[]models.Addressable, p string) error { + return m.GetAddressablesQuery(a, bson.M{"publisher": p}) +} + +func (m *MongoClient) GetAddressablesByAddress(a *[]models.Addressable, add string) error { + return m.GetAddressablesQuery(a, bson.M{"address": add}) +} + +func (m *MongoClient) GetAddressable(d *models.Addressable, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Addressable) + err := col.Find(q).One(d) + if err != nil { + return err + } + + return nil +} + +func (m *MongoClient) DeleteAddressable(a models.Addressable) error { + return m.deleteById(db.Addressable, a.Id.Hex()) +} + +/* ----------------------------- Device Service ----------------------------------*/ +func (m *MongoClient) GetDeviceServiceByName(d *models.DeviceService, n string) error { + return m.GetDeviceService(d, bson.M{"name": n}) +} + +func (m *MongoClient) GetDeviceServiceById(d *models.DeviceService, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetDeviceService(d, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetDeviceServiceByName Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetAllDeviceServices(d *[]models.DeviceService) error { + return m.GetDeviceServices(d, bson.M{}) +} + +func (m *MongoClient) GetDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetDeviceServices(d, bson.M{"addressable.$id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetDeviceServicesByAddressableId Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error { + return m.GetDeviceServices(d, bson.M{"labels": bson.M{"$in": l}}) +} + +func (m *MongoClient) GetDeviceServices(d *[]models.DeviceService, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceService) + mdss := []MongoDeviceService{} + err := col.Find(q).Sort("queryts").All(&mdss) + if err != nil { + return err + } + for _, mds := range mdss { + *d = append(*d, mds.DeviceService) + } + + return nil +} + +func (m *MongoClient) GetDeviceService(d *models.DeviceService, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceService) + mds := MongoDeviceService{} + err := col.Find(q).One(&mds) + if err != nil { + return err + } + *d = mds.DeviceService + + return nil +} + +func (m *MongoClient) AddDeviceService(d *models.DeviceService) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.DeviceService) + + // check if the name exist + count, err := col.Find(bson.M{"name": d.Service.Name}).Count() + if err != nil { + return err + } else if count > 0 { + return db.ErrNotUnique + } + + ts := makeTimestamp() + d.Service.Created = ts + d.Service.Modified = ts + d.Service.Id = bson.NewObjectId() + + // MongoDeviceService handles the DBRefs + mds := MongoDeviceService{DeviceService: *d} + return col.Insert(mds) +} + +func (m *MongoClient) UpdateDeviceService(deviceService models.DeviceService) error { + s := m.session.Copy() + defer s.Close() + c := s.DB(m.database.Name).C(db.DeviceService) + + deviceService.Service.Modified = makeTimestamp() + + // Handle DBRefs + mds := MongoDeviceService{DeviceService: deviceService} + + return c.UpdateId(deviceService.Service.Id, mds) +} + +func (m *MongoClient) DeleteDeviceService(ds models.DeviceService) error { + return m.deleteById(db.DeviceService, ds.Id.Hex()) +} + +// ----------------------Provision Watcher -----------------------------*/ +func (m *MongoClient) GetAllProvisionWatchers(pw *[]models.ProvisionWatcher) error { + return m.GetProvisionWatchers(pw, bson.M{}) +} + +func (m *MongoClient) GetProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error { + return m.GetProvisionWatcher(pw, bson.M{"name": n}) +} + +func (m *MongoClient) GetProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error { + return m.GetProvisionWatchers(pw, bson.M{"identifiers." + k: v}) +} + +func (m *MongoClient) GetProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetProvisionWatchers(pw, bson.M{"service.$id": bson.ObjectIdHex(id)}) + } else { + return errors.New("mgoGetProvisionWatchersByServiceId Invalid Object ID " + id) + } +} + +func (m *MongoClient) GetProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetProvisionWatchers(pw, bson.M{"profile.$id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetProvisionWatcherByProfileId Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetProvisionWatcherById(pw *models.ProvisionWatcher, id string) error { + if bson.IsObjectIdHex(id) { + return m.GetProvisionWatcher(pw, bson.M{"_id": bson.ObjectIdHex(id)}) + } else { + err := errors.New("mgoGetProvisionWatcherById Invalid Object ID " + id) + return err + } +} + +func (m *MongoClient) GetProvisionWatcher(pw *models.ProvisionWatcher, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ProvisionWatcher) + + // Handle DBRefs + var mpw MongoProvisionWatcher + + err := col.Find(q).One(&mpw) + if err != nil { + return err + } + + *pw = mpw.ProvisionWatcher + + return err +} + +func (m *MongoClient) GetProvisionWatchers(pw *[]models.ProvisionWatcher, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ProvisionWatcher) + + // Handle DBRefs + var mpws []MongoProvisionWatcher + + err := col.Find(q).Sort("queryts").All(&mpws) + if err != nil { + return err + } + + for _, mpw := range mpws { + *pw = append(*pw, mpw.ProvisionWatcher) + } + + return nil +} + +func (m *MongoClient) AddProvisionWatcher(pw *models.ProvisionWatcher) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.ProvisionWatcher) + count, err := col.Find(bson.M{"name": pw.Name}).Count() + if err != nil { + return err + } else if count > 0 { + return db.ErrNotUnique + } + + // get Device Service + var dev models.DeviceService + if pw.Service.Service.Id.Hex() != "" { + m.GetDeviceServiceById(&dev, pw.Service.Service.Id.Hex()) + } else if pw.Service.Service.Name != "" { + m.GetDeviceServiceByName(&dev, pw.Service.Service.Name) + } else { + return errors.New("Device Service ID or Name is required") + } + pw.Service = dev + + // get Device Profile + var dp models.DeviceProfile + if pw.Profile.Id.Hex() != "" { + m.GetDeviceProfileById(&dp, pw.Profile.Id.Hex()) + } else if pw.Profile.Name != "" { + m.GetDeviceProfileByName(&dp, pw.Profile.Name) + } else { + return errors.New("Device Profile ID or Name is required") + } + pw.Profile = dp + + // Set data + ts := makeTimestamp() + pw.Created = ts + pw.Modified = ts + pw.Id = bson.NewObjectId() + + // Handle DBRefs + mpw := MongoProvisionWatcher{ProvisionWatcher: *pw} + + return col.Insert(mpw) +} + +func (m *MongoClient) UpdateProvisionWatcher(pw models.ProvisionWatcher) error { + s := m.session.Copy() + defer s.Close() + c := s.DB(m.database.Name).C(db.ProvisionWatcher) + + pw.Modified = makeTimestamp() + + // Handle DBRefs + mpw := MongoProvisionWatcher{ProvisionWatcher: pw} + + return c.UpdateId(mpw.Id, mpw) +} + +func (m *MongoClient) DeleteProvisionWatcher(pw models.ProvisionWatcher) error { + return m.deleteById(db.ProvisionWatcher, pw.Id.Hex()) +} + +// ------------------------Command -------------------------------------*/ +func (m *MongoClient) GetAllCommands(d *[]models.Command) error { + return m.GetCommands(d, bson.M{}) +} + +func (m *MongoClient) GetCommands(d *[]models.Command, q bson.M) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Command) + return col.Find(q).Sort("queryts").All(d) +} + +func (m *MongoClient) GetCommandById(d *models.Command, id string) error { + if bson.IsObjectIdHex(id) { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Command) + return col.Find(bson.M{"_id": bson.ObjectIdHex(id)}).One(d) + } else { + return errors.New("mgoGetCommandById Invalid Object ID " + id) + } +} + +func (m *MongoClient) GetCommandByName(c *[]models.Command, n string) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Command) + return col.Find(bson.M{"name": n}).All(c) +} + +func (m *MongoClient) AddCommand(c *models.Command) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Command) + + ts := makeTimestamp() + c.Created = ts + c.Id = bson.NewObjectId() + return col.Insert(c) +} + +// Update command uses the ID of the command for identification +func (m *MongoClient) UpdateCommand(c *models.Command, r *models.Command) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Command) + if c == nil { + return nil + } + + // Check if the command has a valid ID + if len(c.Id.Hex()) == 0 || !bson.IsObjectIdHex(c.Id.Hex()) { + return errors.New("ID required for updating a command") + } + + // Update the fields + if c.Name != "" { + r.Name = c.Name + } + // TODO check for Get and Put Equality + + if (c.Get.String() != models.Get{}.String()) { + r.Get = c.Get + } + if (c.Put.String() != models.Put{}.String()) { + r.Put = c.Put + } + if c.Origin != 0 { + r.Origin = c.Origin + } + + return col.UpdateId(r.Id, r) +} + +// Delete the command by ID +// Check if the command is still in use by device profiles +func (m *MongoClient) DeleteCommandById(id string) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(db.Command) + + if !bson.IsObjectIdHex(id) { + return errors.New("Invalid ID") + } + + // Check if the command is still in use + query := bson.M{"commands": bson.M{"$elemMatch": bson.M{"_id": bson.ObjectIdHex(id)}}} + count, err := s.DB(m.database.Name).C(db.DeviceProfile).Find(query).Count() + if err != nil { + return err + } + if count > 0 { + return db.ErrCommandStillInUse + } + + return col.RemoveId(bson.ObjectIdHex(id)) +} + +func (m *MongoClient) DeleteByName(c string, n string) error { + s := m.session.Copy() + defer s.Close() + col := s.DB(m.database.Name).C(c) + err := col.Remove(bson.M{"name": n}) + if err != nil { + return err + } + + return nil +} diff --git a/core/metadata/mongo_device.go b/core/db/mongo/mongo_device.go similarity index 89% rename from core/metadata/mongo_device.go rename to core/db/mongo/mongo_device.go index 88c72f6857..0ba3f12a71 100644 --- a/core/metadata/mongo_device.go +++ b/core/db/mongo/mongo_device.go @@ -11,11 +11,10 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package metadata +package mongo import ( - "fmt" - + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -52,13 +51,13 @@ func (md MongoDevice) GetBSON() (interface{}, error) { Name: md.Name, AdminState: md.AdminState, OperatingState: md.OperatingState, - Addressable: mgo.DBRef{Collection: ADDCOL, Id: md.Addressable.Id}, + Addressable: mgo.DBRef{Collection: db.Addressable, Id: md.Addressable.Id}, LastConnected: md.LastConnected, LastReported: md.LastReported, Labels: md.Labels, Location: md.Location, - Service: mgo.DBRef{Collection: DSCOL, Id: md.Service.Service.Id}, - Profile: mgo.DBRef{Collection: DPCOL, Id: md.Profile.Id}, + Service: mgo.DBRef{Collection: db.DeviceService, Id: md.Service.Service.Id}, + Profile: mgo.DBRef{Collection: db.DeviceProfile, Id: md.Profile.Id}, }, nil } @@ -96,21 +95,22 @@ func (md *MongoDevice) SetBSON(raw bson.Raw) error { // De-reference the DBRef fields - s := getMongoSessionCopy() - if s == nil { - return fmt.Errorf("Could not obtain a mongo session") + m, err := getCurrentMongoClient() + if err != nil { + return err } + s := m.session.Copy() defer s.Close() - addCol := s.DB(DB).C(ADDCOL) - dsCol := s.DB(DB).C(DSCOL) - dpCol := s.DB(DB).C(DPCOL) + addCol := s.DB(m.database.Name).C(db.Addressable) + dsCol := s.DB(m.database.Name).C(db.DeviceService) + dpCol := s.DB(m.database.Name).C(db.DeviceProfile) var a models.Addressable var mdp MongoDeviceProfile var mds MongoDeviceService - err := addCol.Find(bson.M{"_id": decoded.Addressable.Id}).One(&a) + err = addCol.Find(bson.M{"_id": decoded.Addressable.Id}).One(&a) if err != nil { return err } diff --git a/core/metadata/mongo_deviceprofile.go b/core/db/mongo/mongo_deviceprofile.go similarity index 95% rename from core/metadata/mongo_deviceprofile.go rename to core/db/mongo/mongo_deviceprofile.go index 9200b9d6f8..7533ce71b2 100644 --- a/core/metadata/mongo_deviceprofile.go +++ b/core/db/mongo/mongo_deviceprofile.go @@ -11,11 +11,10 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package metadata +package mongo import ( - "fmt" - + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -32,7 +31,7 @@ func (mdp MongoDeviceProfile) GetBSON() (interface{}, error) { // Get the commands from the device profile and turn them into DBRef objects var dbRefs []mgo.DBRef for _, command := range mdp.Commands { - dbRefs = append(dbRefs, mgo.DBRef{Collection: COMCOL, Id: command.Id}) + dbRefs = append(dbRefs, mgo.DBRef{Collection: db.Command, Id: command.Id}) } return struct { @@ -106,12 +105,14 @@ func (mdp *MongoDeviceProfile) SetBSON(raw bson.Raw) error { mdp.Resources = decoded.Resources // De-reference the DBRef fields - s := getMongoSessionCopy() - if s == nil { - return fmt.Errorf("Could not obtain a mongo session") + m, err := getCurrentMongoClient() + if err != nil { + return err } + s := m.session.Copy() defer s.Close() - comCol := s.DB(DB).C(COMCOL) + + comCol := s.DB(m.database.Name).C(db.Command) var commands []models.Command diff --git a/core/metadata/mongo_deviceservice.go b/core/db/mongo/mongo_deviceservice.go similarity index 92% rename from core/metadata/mongo_deviceservice.go rename to core/db/mongo/mongo_deviceservice.go index 4c4bb39e29..f22381b28a 100644 --- a/core/metadata/mongo_deviceservice.go +++ b/core/db/mongo/mongo_deviceservice.go @@ -11,11 +11,10 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package metadata +package mongo import ( - "fmt" - + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -45,7 +44,7 @@ func (mds MongoDeviceService) GetBSON() (interface{}, error) { Name: mds.Service.Name, AdminState: mds.AdminState, OperatingState: mds.Service.OperatingState, - Addressable: mgo.DBRef{Collection: ADDCOL, Id: mds.Service.Addressable.Id}, + Addressable: mgo.DBRef{Collection: db.Addressable, Id: mds.Service.Addressable.Id}, LastConnected: mds.Service.LastConnected, LastReported: mds.Service.LastReported, Labels: mds.Service.Labels, @@ -82,17 +81,18 @@ func (mds *MongoDeviceService) SetBSON(raw bson.Raw) error { mds.Service.Labels = decoded.Labels // De-reference the DBRef fields - s := getMongoSessionCopy() - if s == nil { - return fmt.Errorf("Could not obtain a mongo session") + m, err := getCurrentMongoClient() + if err != nil { + return err } + s := m.session.Copy() defer s.Close() - addCol := s.DB(DB).C(ADDCOL) + addCol := s.DB(m.database.Name).C(db.Addressable) var a models.Addressable - err := addCol.Find(bson.M{"_id": decoded.Addressable.Id}).One(&a) + err = addCol.Find(bson.M{"_id": decoded.Addressable.Id}).One(&a) if err != nil { return err } diff --git a/core/metadata/mongo_provisionwatcher.go b/core/db/mongo/mongo_provisionwatcher.go similarity index 89% rename from core/metadata/mongo_provisionwatcher.go rename to core/db/mongo/mongo_provisionwatcher.go index 77026ab35a..9b22bb74c3 100644 --- a/core/metadata/mongo_provisionwatcher.go +++ b/core/db/mongo/mongo_provisionwatcher.go @@ -11,11 +11,10 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package metadata +package mongo import ( - "fmt" - + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -42,8 +41,8 @@ func (mpw MongoProvisionWatcher) GetBSON() (interface{}, error) { Id: mpw.Id, Name: mpw.Name, Identifiers: mpw.Identifiers, - Profile: mgo.DBRef{Collection: DPCOL, Id: mpw.Profile.Id}, - Service: mgo.DBRef{Collection: DSCOL, Id: mpw.Service.Service.Id}, + Profile: mgo.DBRef{Collection: db.DeviceProfile, Id: mpw.Profile.Id}, + Service: mgo.DBRef{Collection: db.DeviceService, Id: mpw.Service.Service.Id}, OperatingState: mpw.OperatingState, }, nil } @@ -73,14 +72,15 @@ func (mpw *MongoProvisionWatcher) SetBSON(raw bson.Raw) error { mpw.OperatingState = decoded.OperatingState // De-reference the DBRef fields - s := getMongoSessionCopy() - if s == nil { - return fmt.Errorf("Could not obtain a mongo session") + m, err := getCurrentMongoClient() + if err != nil { + return err } + s := m.session.Copy() defer s.Close() - profCol := s.DB(DB).C(DPCOL) - servCol := s.DB(DB).C(DSCOL) + profCol := s.DB(m.database.Name).C(db.DeviceProfile) + servCol := s.DB(m.database.Name).C(db.DeviceService) var mdp MongoDeviceProfile var mds MongoDeviceService diff --git a/core/metadata/mongo_scheduleevent.go b/core/db/mongo/mongo_scheduleevent.go similarity index 91% rename from core/metadata/mongo_scheduleevent.go rename to core/db/mongo/mongo_scheduleevent.go index 06f8f0b365..185593371d 100644 --- a/core/metadata/mongo_scheduleevent.go +++ b/core/db/mongo/mongo_scheduleevent.go @@ -11,11 +11,10 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package metadata +package mongo import ( - "fmt" - + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" @@ -44,7 +43,7 @@ func (mse MongoScheduleEvent) GetBSON() (interface{}, error) { Schedule: mse.Schedule, Parameters: mse.Parameters, Service: mse.Service, - Addressable: mgo.DBRef{Collection: ADDCOL, Id: mse.Addressable.Id}, + Addressable: mgo.DBRef{Collection: db.Addressable, Id: mse.Addressable.Id}, }, nil } @@ -74,13 +73,14 @@ func (mse *MongoScheduleEvent) SetBSON(raw bson.Raw) error { mse.Service = decoded.Service // De-reference the DBRef fields - s := getMongoSessionCopy() - if s == nil { - return fmt.Errorf("Could not obtain a mongo session") + m, err := getCurrentMongoClient() + if err != nil { + return err } + s := m.session.Copy() defer s.Close() - addCol := s.DB(DB).C(ADDCOL) + addCol := s.DB(m.database.Name).C(db.Addressable) var a models.Addressable diff --git a/core/db/mongo/mongoevent.go b/core/db/mongo/mongoevent.go index e4dc649937..0ef3450af9 100644 --- a/core/db/mongo/mongoevent.go +++ b/core/db/mongo/mongoevent.go @@ -94,7 +94,7 @@ func (me *MongoEvent) SetBSON(raw bson.Raw) error { // Get all of the reading objects for _, rRef := range decoded.Readings { var reading models.Reading - err := mc.Database.C(db.ReadingsCollection).FindId(rRef.Id).One(&reading) + err := mc.database.C(db.ReadingsCollection).FindId(rRef.Id).One(&reading) if err != nil { return err } diff --git a/core/db/test/db.go b/core/db/test/db.go index 870ffe17fb..ac42f0133c 100644 --- a/core/db/test/db.go +++ b/core/db/test/db.go @@ -63,6 +63,7 @@ func populateDbEvents(db clients.DBClient, count int, pushed int64) (bson.Object e.Pushed = pushed var err error id, err = db.AddEvent(&e) + fmt.Printf("%s -> %v\n", name, err) if err != nil { return id, err } @@ -619,6 +620,12 @@ func testDBValueDescriptors(t *testing.T, db clients.DBClient) { } func TestDataDB(t *testing.T, db clients.DBClient) { + + err := db.Connect() + if err != nil { + t.Fatalf("Could not connect with mongodb: %v", err) + } + testDBReadings(t, db) testDBEvents(t, db) testDBValueDescriptors(t, db) diff --git a/core/metadata/const.go b/core/metadata/const.go index a2042cd46e..27b34557a2 100644 --- a/core/metadata/const.go +++ b/core/metadata/const.go @@ -13,10 +13,6 @@ *******************************************************************************/ package metadata -import ( - "errors" -) - // Struct used to pase the JSON configuration file type ConfigurationStruct struct { DBType string @@ -57,34 +53,14 @@ var configuration ConfigurationStruct = ConfigurationStruct{} // Needs to be ini var ( /* -------------- CONFIG for METADATA -------------------- */ - db DBClient - PROTOCOL = "http" - SERVERPORT = "48081" - DOCKERMONGO = "edgex-mongo:27017" - DBUSER = "meta" - DBPASS = "password" - MONGODATABASE = "metadata" + dbClient DBClient +) +const ( MAX_LIMIT int = 1000 - /* ----------------------- CONSTANTS ----------------------------*/ - REST = "http" - MONGOSTR = "mongo" - DB = "metadata" - DEVICECOL = "device" - DPCOL = "deviceProfile" - DSCOL = "deviceService" - ADDCOL = "addressable" - COMCOL = "command" - DRCOL = "deviceReport" - SECOL = "scheduleEvent" - SCOL = "schedule" - PWCOL = "provisionWatcher" - TIMELAYOUT = "20060102T150405" - /* ---------------- URL PARAM NAMES -----------------------*/ ID = "id" - _ID = "_id" NAME = "name" OPSTATE = "opstate" URLADMINSTATE = "adminstate" @@ -103,7 +79,6 @@ var ( SERVICENAME = "servicename" SERVICEID = "serviceid" LABEL = "label" - LABELS = "labels" PROFILE = "profile" PROFILEID = "profileid" PROFILENAME = "profilename" @@ -124,21 +99,14 @@ var ( ADDRESS = "address" COMMAND = "command" DEVICE = "device" - OPERATINGSTATE = "operatingState" PROVISIONWATCHER = "provisionwatcher" IDENTIFIER = "identifier" - IDENTIFIERS = "identifiers" KEY = "key" VALUE = "value" VALUEDESCRIPTORSFOR = "valueDescriptorsFor" DEVICEADDRESSABLES = "deviceaddressables" DEVICEADDRESSABLESBYNAME = "deviceaddressablesbyname" - /* ----------------------- ERRORS ----------------------------*/ - ErrNotFound = errors.New("Not found") - ErrDuplicateName = errors.New("Duplicate name for the resource") - ErrDuplicateCommandInProfile = errors.New("Duplicate name for command in device profile") - ErrCommandStillInUse = errors.New("Command is still in use by device profiles") /* TODO ENUM */ LOCKED = "LOCKED" UNLOCKED = "UNLOCKED" diff --git a/core/metadata/dbOps.go b/core/metadata/dbOps.go index d30e13daf0..1cf0f29a0e 100644 --- a/core/metadata/dbOps.go +++ b/core/metadata/dbOps.go @@ -14,6 +14,8 @@ package metadata import ( + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/db/mongo" "github.com/edgexfoundry/edgex-go/core/domain/enums" "github.com/edgexfoundry/edgex-go/core/domain/models" ) @@ -24,104 +26,104 @@ type DBClient interface { Connect() error // Schedule event - getAllScheduleEvents(se *[]models.ScheduleEvent) error - addScheduleEvent(se *models.ScheduleEvent) error - getScheduleEventByName(se *models.ScheduleEvent, n string) error - updateScheduleEvent(se models.ScheduleEvent) error - getScheduleEventById(se *models.ScheduleEvent, id string) error - getScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error - getScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error - getScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error - deleteScheduleEvent(se models.ScheduleEvent) error + GetAllScheduleEvents(se *[]models.ScheduleEvent) error + AddScheduleEvent(se *models.ScheduleEvent) error + GetScheduleEventByName(se *models.ScheduleEvent, n string) error + UpdateScheduleEvent(se models.ScheduleEvent) error + GetScheduleEventById(se *models.ScheduleEvent, id string) error + GetScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error + GetScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error + GetScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error + DeleteScheduleEvent(se models.ScheduleEvent) error // Schedule - getAllSchedules(s *[]models.Schedule) error - addSchedule(s *models.Schedule) error - getScheduleByName(s *models.Schedule, n string) error - updateSchedule(s models.Schedule) error - getScheduleById(s *models.Schedule, id string) error - deleteSchedule(s models.Schedule) error + GetAllSchedules(s *[]models.Schedule) error + AddSchedule(s *models.Schedule) error + GetScheduleByName(s *models.Schedule, n string) error + UpdateSchedule(s models.Schedule) error + GetScheduleById(s *models.Schedule, id string) error + DeleteSchedule(s models.Schedule) error // Device Report - getAllDeviceReports(dr *[]models.DeviceReport) error - getDeviceReportByDeviceName(dr *[]models.DeviceReport, n string) error - getDeviceReportByName(dr *models.DeviceReport, n string) error - getDeviceReportById(dr *models.DeviceReport, id string) error - addDeviceReport(dr *models.DeviceReport) error - updateDeviceReport(dr *models.DeviceReport) error - getDeviceReportsByScheduleEventName(dr *[]models.DeviceReport, n string) error - deleteDeviceReport(dr models.DeviceReport) error + GetAllDeviceReports(dr *[]models.DeviceReport) error + GetDeviceReportByDeviceName(dr *[]models.DeviceReport, n string) error + GetDeviceReportByName(dr *models.DeviceReport, n string) error + GetDeviceReportById(dr *models.DeviceReport, id string) error + AddDeviceReport(dr *models.DeviceReport) error + UpdateDeviceReport(dr *models.DeviceReport) error + GetDeviceReportsByScheduleEventName(dr *[]models.DeviceReport, n string) error + DeleteDeviceReport(dr models.DeviceReport) error // Device - updateDevice(d models.Device) error - getDeviceById(d *models.Device, id string) error - getDeviceByName(d *models.Device, n string) error - getAllDevices(d *[]models.Device) error - getDevicesByProfileId(d *[]models.Device, pid string) error - getDevicesByServiceId(d *[]models.Device, sid string) error - getDevicesByAddressableId(d *[]models.Device, aid string) error - getDevicesWithLabel(d *[]models.Device, l []string) error - addDevice(d *models.Device) error - deleteDevice(d models.Device) error - updateDeviceProfile(dp *models.DeviceProfile) error - addDeviceProfile(d *models.DeviceProfile) error - getAllDeviceProfiles(d *[]models.DeviceProfile) error - getDeviceProfileById(d *models.DeviceProfile, id string) error - deleteDeviceProfile(dp models.DeviceProfile) error - getDeviceProfilesByModel(dp *[]models.DeviceProfile, m string) error - getDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error - getDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error - getDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error - getDeviceProfileByName(dp *models.DeviceProfile, n string) error + UpdateDevice(d models.Device) error + GetDeviceById(d *models.Device, id string) error + GetDeviceByName(d *models.Device, n string) error + GetAllDevices(d *[]models.Device) error + GetDevicesByProfileId(d *[]models.Device, pid string) error + GetDevicesByServiceId(d *[]models.Device, sid string) error + GetDevicesByAddressableId(d *[]models.Device, aid string) error + GetDevicesWithLabel(d *[]models.Device, l []string) error + AddDevice(d *models.Device) error + DeleteDevice(d models.Device) error + UpdateDeviceProfile(dp *models.DeviceProfile) error + AddDeviceProfile(d *models.DeviceProfile) error + GetAllDeviceProfiles(d *[]models.DeviceProfile) error + GetDeviceProfileById(d *models.DeviceProfile, id string) error + DeleteDeviceProfile(dp models.DeviceProfile) error + GetDeviceProfilesByModel(dp *[]models.DeviceProfile, m string) error + GetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error + GetDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error + GetDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error + GetDeviceProfileByName(dp *models.DeviceProfile, n string) error - updateAddressable(ra *models.Addressable, r *models.Addressable) error - addAddressable(a *models.Addressable) error - getAddressableById(a *models.Addressable, id string) error - getAddressableByName(a *models.Addressable, n string) error - getAddressablesByTopic(a *[]models.Addressable, t string) error - getAddressablesByPort(a *[]models.Addressable, p int) error - getAddressablesByPublisher(a *[]models.Addressable, p string) error - getAddressablesByAddress(a *[]models.Addressable, add string) error - getAddressables(d *[]models.Addressable) error - deleteAddressable(a models.Addressable) error + UpdateAddressable(ra *models.Addressable, r *models.Addressable) error + AddAddressable(a *models.Addressable) error + GetAddressableById(a *models.Addressable, id string) error + GetAddressableByName(a *models.Addressable, n string) error + GetAddressablesByTopic(a *[]models.Addressable, t string) error + GetAddressablesByPort(a *[]models.Addressable, p int) error + GetAddressablesByPublisher(a *[]models.Addressable, p string) error + GetAddressablesByAddress(a *[]models.Addressable, add string) error + GetAddressables(d *[]models.Addressable) error + DeleteAddressable(a models.Addressable) error // Device service - updateDeviceService(ds models.DeviceService) error - getDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error - getDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error - getDeviceServiceById(d *models.DeviceService, id string) error - getDeviceServiceByName(d *models.DeviceService, n string) error - getAllDeviceServices(d *[]models.DeviceService) error - addDeviceService(ds *models.DeviceService) error - deleteDeviceService(ds models.DeviceService) error + UpdateDeviceService(ds models.DeviceService) error + GetDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error + GetDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error + GetDeviceServiceById(d *models.DeviceService, id string) error + GetDeviceServiceByName(d *models.DeviceService, n string) error + GetAllDeviceServices(d *[]models.DeviceService) error + AddDeviceService(ds *models.DeviceService) error + DeleteDeviceService(ds models.DeviceService) error // Provision watcher - getProvisionWatcherById(pw *models.ProvisionWatcher, id string) error - getAllProvisionWatchers(pw *[]models.ProvisionWatcher) error - getProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error - getProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error - getProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error - getProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error - addProvisionWatcher(pw *models.ProvisionWatcher) error - updateProvisionWatcher(pw models.ProvisionWatcher) error - deleteProvisionWatcher(pw models.ProvisionWatcher) error + GetProvisionWatcherById(pw *models.ProvisionWatcher, id string) error + GetAllProvisionWatchers(pw *[]models.ProvisionWatcher) error + GetProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error + GetProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error + GetProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error + GetProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error + AddProvisionWatcher(pw *models.ProvisionWatcher) error + UpdateProvisionWatcher(pw models.ProvisionWatcher) error + DeleteProvisionWatcher(pw models.ProvisionWatcher) error // Command - getCommandById(c *models.Command, id string) error - getCommandByName(d *[]models.Command, id string) error - addCommand(c *models.Command) error - getAllCommands(d *[]models.Command) error - updateCommand(c *models.Command, r *models.Command) error - deleteCommandById(id string) error + GetCommandById(c *models.Command, id string) error + GetCommandByName(d *[]models.Command, id string) error + AddCommand(c *models.Command) error + GetAllCommands(d *[]models.Command) error + UpdateCommand(c *models.Command, r *models.Command) error + DeleteCommandById(id string) error - getDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error + GetDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error } -func getDatabase(dbType string) (DBClient, error) { +func getDatabase(dbType string, config db.Configuration) (DBClient, error) { switch dbType { case enums.MongoStr: - return &mongoDB{}, nil + return mongo.NewClient(config), nil case enums.MemoryStr: } - return nil, ErrNotFound + return nil, db.ErrNotFound } diff --git a/core/metadata/init.go b/core/metadata/init.go index 12f19629c1..662a023c0d 100644 --- a/core/metadata/init.go +++ b/core/metadata/init.go @@ -15,9 +15,9 @@ package metadata import ( "fmt" - "strconv" "strings" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/internal" consulclient "github.com/edgexfoundry/edgex-go/support/consul-client" logger "github.com/edgexfoundry/edgex-go/support/logging-client" @@ -53,31 +53,31 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient) error { configuration = conf //TODO: The above two are set due to global scope throughout the package. How can this be eliminated / refactored? - // Update Service CONSTANTS - MONGODATABASE = configuration.MongoDatabaseName - PROTOCOL = configuration.Protocol - SERVERPORT = strconv.Itoa(configuration.ServicePort) - dbType := configuration.DBType - DOCKERMONGO = configuration.MongoDBHost + ":" + strconv.Itoa(configuration.MongoDBPort) - DBUSER = configuration.MongoDBUserName - DBPASS = configuration.MongoDBPassword - // Initialize notificationsClient based on configuration notifications.SetConfiguration(configuration.SupportNotificationsHost, configuration.SupportNotificationsPort) var err error - // Connect to the database - db, err = getDatabase(dbType) + dbConfig := db.Configuration{ + Host: configuration.MongoDBHost, + Port: configuration.MongoDBPort, + Timeout: 0, + DatabaseName: configuration.MongoDatabaseName, + Username: configuration.MongoDBUserName, + Password: configuration.MongoDBPassword, + } + // Create database client + dbClient, err = getDatabase(configuration.DBType, dbConfig) if err != nil { return err } - return db.Connect() + // Connect to the database + return dbClient.Connect() } func Destruct() { - if db != nil { - db.CloseSession() - db = nil + if dbClient != nil { + dbClient.CloseSession() + dbClient = nil } } diff --git a/core/metadata/mongoOps.go b/core/metadata/mongoOps.go deleted file mode 100644 index 101956fe1a..0000000000 --- a/core/metadata/mongoOps.go +++ /dev/null @@ -1,1050 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Dell Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - *******************************************************************************/ -package metadata - -import ( - "errors" - "time" - - "github.com/edgexfoundry/edgex-go/core/domain/models" - "gopkg.in/mgo.v2" - "gopkg.in/mgo.v2/bson" -) - -func makeTimestamp() int64 { - return time.Now().UnixNano() / int64(time.Millisecond) -} - -type mongoDB struct { - s *mgo.Session -} - -func getMongoSessionCopy() *mgo.Session { - m, ok := db.(*mongoDB) - if ok { - return m.s.Copy() - } else { - return nil - } -} - -func (m *mongoDB) Connect() error { - mongoDBDialInfo := &mgo.DialInfo{ - Addrs: []string{DOCKERMONGO}, - Timeout: time.Duration(configuration.MongoDBConnectTimeout) * time.Millisecond, - Database: MONGODATABASE, - Username: DBUSER, - Password: DBPASS, - } - var err error - m.s, err = mgo.DialWithInfo(mongoDBDialInfo) - if err != nil { - return err - } - - // Set timeout based on configuration - m.s.SetSocketTimeout(time.Duration(configuration.MongoDBConnectTimeout) * time.Millisecond) - return nil -} - -func (m *mongoDB) CloseSession() { - if m.s != nil { - m.s.Close() - m.s = nil - } -} - -/* -----------------------Schedule Event ------------------------*/ -func (m *mongoDB) updateScheduleEvent(se models.ScheduleEvent) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SECOL) - - se.Modified = makeTimestamp() - - // Handle DBRefs - mse := MongoScheduleEvent{ScheduleEvent: se} - - return col.UpdateId(se.Id, mse) -} - -func (m *mongoDB) addScheduleEvent(se *models.ScheduleEvent) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SECOL) - count, err := col.Find(bson.M{NAME: se.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return ErrDuplicateName - } - ts := makeTimestamp() - se.Created = ts - se.Modified = ts - se.Id = bson.NewObjectId() - - // Handle DBRefs - mse := MongoScheduleEvent{ScheduleEvent: *se} - - return col.Insert(mse) -} - -func (m *mongoDB) getAllScheduleEvents(se *[]models.ScheduleEvent) error { - return m.getScheduleEvents(se, bson.M{}) -} - -func (m *mongoDB) getScheduleEventByName(se *models.ScheduleEvent, n string) error { - return m.getScheduleEvent(se, bson.M{NAME: n}) -} - -func (m *mongoDB) getScheduleEventById(se *models.ScheduleEvent, id string) error { - if bson.IsObjectIdHex(id) { - return m.getScheduleEvent(se, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetScheduleEventById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getScheduleEventsByScheduleName(se *[]models.ScheduleEvent, n string) error { - return m.getScheduleEvents(se, bson.M{SCHEDULE: n}) -} - -func (m *mongoDB) getScheduleEventsByAddressableId(se *[]models.ScheduleEvent, id string) error { - if bson.IsObjectIdHex(id) { - return m.getScheduleEvents(se, bson.M{ADDRESSABLE + ".$id": bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetScheduleEventsByAddressableId Invalid Object ID" + id) - return err - } -} - -func (m *mongoDB) getScheduleEventsByServiceName(se *[]models.ScheduleEvent, n string) error { - return m.getScheduleEvents(se, bson.M{SERVICE: n}) -} - -func (m *mongoDB) getScheduleEvent(se *models.ScheduleEvent, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SECOL) - - // Handle DBRef - var mse MongoScheduleEvent - - err := col.Find(q).One(&mse) - if err != nil { - return err - } - - *se = mse.ScheduleEvent - - return err -} - -func (m *mongoDB) getScheduleEvents(se *[]models.ScheduleEvent, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SECOL) - - // Handle the DBRef - var mses []MongoScheduleEvent - - err := col.Find(q).Sort(QUERYTS).All(&mses) - if err != nil { - return err - } - - for _, mse := range mses { - *se = append(*se, mse.ScheduleEvent) - } - - return nil -} - -func (m *mongoDB) deleteScheduleEvent(se models.ScheduleEvent) error { - return m.deleteById(SECOL, se.Id.Hex()) -} - -// --------------------------Schedule ---------------------------*/ -func (m *mongoDB) getAllSchedules(s *[]models.Schedule) error { - return m.getSchedules(s, bson.M{}) -} - -func (m *mongoDB) getScheduleByName(s *models.Schedule, n string) error { - return m.getSchedule(s, bson.M{NAME: n}) -} - -func (m *mongoDB) getScheduleById(s *models.Schedule, id string) error { - if bson.IsObjectIdHex(id) { - return m.getSchedule(s, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetScheduleById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) addSchedule(sch *models.Schedule) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SCOL) - count, err := col.Find(bson.M{NAME: sch.Name}).Count() - if err != nil { - return err - } else if count > 0 { - err := errors.New("Schedule already exist") - return err - } - - ts := makeTimestamp() - sch.Created = ts - sch.Modified = ts - sch.Id = bson.NewObjectId() - return col.Insert(s) -} - -func (m *mongoDB) updateSchedule(sch models.Schedule) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SCOL) - - sch.Modified = makeTimestamp() - - if err := col.UpdateId(sch.Id, sch); err != nil { - return err - } - - return nil -} - -func (m *mongoDB) deleteSchedule(s models.Schedule) error { - return m.deleteById(SCOL, s.Id.Hex()) -} - -func (m *mongoDB) getSchedule(sch *models.Schedule, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SCOL) - return col.Find(q).One(sch) -} - -func (m *mongoDB) getSchedules(sch *[]models.Schedule, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(SCOL) - return col.Find(q).Sort(QUERYTS).All(sch) -} - -/* ----------------------Device Report --------------------------*/ -func (m *mongoDB) getAllDeviceReports(d *[]models.DeviceReport) error { - return m.getDeviceReports(d, bson.M{}) -} - -func (m *mongoDB) getDeviceReportByName(d *models.DeviceReport, n string) error { - return m.getDeviceReport(d, bson.M{NAME: n}) -} - -func (m *mongoDB) getDeviceReportByDeviceName(d *[]models.DeviceReport, n string) error { - return m.getDeviceReports(d, bson.M{DEVICE: n}) -} - -func (m *mongoDB) getDeviceReportById(d *models.DeviceReport, id string) error { - if bson.IsObjectIdHex(id) { - return m.getDeviceReport(d, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetDeviceReportById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getDeviceReportsByScheduleEventName(d *[]models.DeviceReport, n string) error { - return m.getDeviceReports(d, bson.M{"event": n}) -} - -func (m *mongoDB) getDeviceReports(d *[]models.DeviceReport, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DRCOL) - return col.Find(q).Sort(QUERYTS).All(d) -} - -func (m *mongoDB) getDeviceReport(d *models.DeviceReport, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DRCOL) - return col.Find(q).One(d) -} - -func (m *mongoDB) addDeviceReport(d *models.DeviceReport) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DRCOL) - count, err := col.Find(bson.M{NAME: d.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return ErrDuplicateName - } - ts := makeTimestamp() - d.Created = ts - d.Id = bson.NewObjectId() - return col.Insert(d) -} - -func (m *mongoDB) updateDeviceReport(dr *models.DeviceReport) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DRCOL) - - return col.UpdateId(dr.Id, dr) -} - -func (m *mongoDB) deleteDeviceReport(dr models.DeviceReport) error { - return m.deleteById(DRCOL, dr.Id.Hex()) -} - -/* ----------------------------- Device ---------------------------------- */ -func (m *mongoDB) addDevice(d *models.Device) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DEVICECOL) - - // Check if the name exist (Device names must be unique) - count, err := col.Find(bson.M{NAME: d.Name}).Count() - if err != nil { - return err - } - if count > 0 { - return ErrDuplicateName - } - ts := makeTimestamp() - d.Created = ts - d.Modified = ts - d.Id = bson.NewObjectId() - - // Wrap the device in MongoDevice (For DBRefs) - md := MongoDevice{Device: *d} - - return col.Insert(md) -} - -func (m *mongoDB) updateDevice(rd models.Device) error { - s := m.s.Copy() - defer s.Close() - c := s.DB(DB).C(DEVICECOL) - - // Copy over the DBRefs - md := MongoDevice{Device: rd} - - return c.UpdateId(rd.Id, md) -} - -func (m *mongoDB) deleteDevice(d models.Device) error { - return m.deleteById(DEVICECOL, d.Id.Hex()) -} - -func (m *mongoDB) getAllDevices(d *[]models.Device) error { - return m.getDevices(d, nil) -} - -func (m *mongoDB) getDevicesByProfileId(d *[]models.Device, pid string) error { - if bson.IsObjectIdHex(pid) { - return m.getDevices(d, bson.M{PROFILE + "." + "$id": bson.ObjectIdHex(pid)}) - } else { - err := errors.New("mgoGetDevicesByProfileId Invalid Object ID " + pid) - return err - } -} - -func (m *mongoDB) getDeviceById(d *models.Device, id string) error { - if bson.IsObjectIdHex(id) { - return m.getDevice(d, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetDeviceById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getDeviceByName(d *models.Device, n string) error { - return m.getDevice(d, bson.M{NAME: n}) -} - -func (m *mongoDB) getDevicesByServiceId(d *[]models.Device, sid string) error { - if bson.IsObjectIdHex(sid) { - return m.getDevices(d, bson.M{SERVICE + "." + "$id": bson.ObjectIdHex(sid)}) - } else { - err := errors.New("mgoGetDevicesByServiceId Invalid Object ID " + sid) - return err - } -} - -func (m *mongoDB) getDevicesByAddressableId(d *[]models.Device, aid string) error { - if bson.IsObjectIdHex(aid) { - // Check if the addressable exists - var a *models.Addressable - if m.getAddressableById(a, aid) == mgo.ErrNotFound { - return mgo.ErrNotFound - } - return m.getDevices(d, bson.M{ADDRESSABLE + "." + "$id": bson.ObjectIdHex(aid)}) - } else { - err := errors.New("mgoGetDevicesByAddressableId Invalid Object ID " + aid) - return err - } -} - -func (m *mongoDB) getDevicesWithLabel(d *[]models.Device, l []string) error { - return m.getDevices(d, bson.M{LABELS: bson.M{"$in": l}}) -} - -func (m *mongoDB) getDevices(d *[]models.Device, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DEVICECOL) - mds := []MongoDevice{} - - err := col.Find(q).Sort(QUERYTS).All(&mds) - if err != nil { - return err - } - - for _, md := range mds { - *d = append(*d, md.Device) - } - - return nil -} - -func (m *mongoDB) getDevice(d *models.Device, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DEVICECOL) - md := MongoDevice{} - - err := col.Find(q).One(&md) - if err != nil { - return err - } - - *d = md.Device - - return nil -} - -/* -----------------------------Device Profile -----------------------------*/ -func (m *mongoDB) getDeviceProfileById(d *models.DeviceProfile, id string) error { - if bson.IsObjectIdHex(id) { - return m.getDeviceProfile(d, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetDeviceProfileById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getAllDeviceProfiles(dp *[]models.DeviceProfile) error { - return m.getDeviceProfiles(dp, nil) -} - -func (m *mongoDB) getDeviceProfilesByModel(dp *[]models.DeviceProfile, model string) error { - return m.getDeviceProfiles(dp, bson.M{MODEL: model}) -} - -func (m *mongoDB) getDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error { - return m.getDeviceProfiles(dp, bson.M{LABELS: bson.M{"$in": l}}) -} -func (m *mongoDB) getDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error { - return m.getDeviceProfiles(dp, bson.M{MANUFACTURER: man, MODEL: mod}) -} -func (m *mongoDB) getDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error { - return m.getDeviceProfiles(dp, bson.M{MANUFACTURER: man}) -} -func (m *mongoDB) getDeviceProfileByName(dp *models.DeviceProfile, n string) error { - return m.getDeviceProfile(dp, bson.M{NAME: n}) -} - -// Get device profiles with the passed query -func (m *mongoDB) getDeviceProfiles(d *[]models.DeviceProfile, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DPCOL) - - // Handle the DBRefs - var mdps []MongoDeviceProfile - err := col.Find(q).Sort(QUERYTS).All(&mdps) - if err != nil { - return err - } - - for _, mdp := range mdps { - *d = append(*d, mdp.DeviceProfile) - } - - return err -} - -// Get device profile with the passed query -func (m *mongoDB) getDeviceProfile(d *models.DeviceProfile, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DPCOL) - - // Handle the DBRefs - var mdp MongoDeviceProfile - err := col.Find(q).One(&mdp) - if err != nil { - return err - } - - *d = mdp.DeviceProfile - - return err -} - -func (m *mongoDB) addDeviceProfile(dp *models.DeviceProfile) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DPCOL) - count, err := col.Find(bson.M{NAME: dp.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return ErrDuplicateName - } - for i := 0; i < len(dp.Commands); i++ { - if err := m.addCommand(&dp.Commands[i]); err != nil { - return err - } - } - ts := makeTimestamp() - dp.Created = ts - dp.Modified = ts - dp.Id = bson.NewObjectId() - - mdp := MongoDeviceProfile{DeviceProfile: *dp} - - return col.Insert(mdp) -} - -func (m *mongoDB) updateDeviceProfile(dp *models.DeviceProfile) error { - s := m.s.Copy() - defer s.Close() - c := s.DB(DB).C(DPCOL) - - mdp := MongoDeviceProfile{DeviceProfile: *dp} - mdp.Modified = makeTimestamp() - - return c.UpdateId(mdp.Id, mdp) -} - -// Get the device profiles that are currently using the command -func (m *mongoDB) getDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error { - query := bson.M{"commands": bson.M{"$elemMatch": bson.M{"$id": c.Id}}} - return m.getDeviceProfiles(dp, query) -} - -func (m *mongoDB) deleteDeviceProfile(dp models.DeviceProfile) error { - return m.deleteById(DPCOL, dp.Id.Hex()) -} - -// -----------------------------------Addressable --------------------------*/ -func (m *mongoDB) updateAddressable(ra *models.Addressable, r *models.Addressable) error { - s := m.s.Copy() - - defer s.Close() - c := s.DB(DB).C(ADDCOL) - if ra == nil { - return nil - } - if ra.Name != "" { - r.Name = ra.Name - } - if ra.Protocol != "" { - r.Protocol = ra.Protocol - } - if ra.Address != "" { - r.Address = ra.Address - } - if ra.Port != int(0) { - r.Port = ra.Port - } - if ra.Path != "" { - r.Path = ra.Path - } - if ra.Publisher != "" { - r.Publisher = ra.Publisher - } - if ra.User != "" { - r.User = ra.User - } - if ra.Password != "" { - r.Password = ra.Password - } - if ra.Topic != "" { - r.Topic = ra.Topic - } - if err := c.UpdateId(r.Id, r); err != nil { - return err - } - return nil -} - -func (m *mongoDB) getAddressables(d *[]models.Addressable) error { - return m.getAddressablesQuery(d, bson.M{}) -} - -func (m *mongoDB) getAddressablesQuery(d *[]models.Addressable, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(ADDCOL) - err := col.Find(q).Sort(QUERYTS).All(d) - if err != nil { - return err - } - - return nil -} - -func (m *mongoDB) getAddressableById(a *models.Addressable, id string) error { - if bson.IsObjectIdHex(id) { - return m.getAddressable(a, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetAddressableById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) addAddressable(a *models.Addressable) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(ADDCOL) - - // check if the name exist - count, err := col.Find(bson.M{NAME: a.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return ErrDuplicateName - } - - ts := makeTimestamp() - a.Created = ts - a.Id = bson.NewObjectId() - err = col.Insert(a) - if err != nil { - return err - } - - return nil -} - -func (m *mongoDB) getAddressableByName(a *models.Addressable, n string) error { - return m.getAddressable(a, bson.M{NAME: n}) -} - -func (m *mongoDB) getAddressablesByTopic(a *[]models.Addressable, t string) error { - return m.getAddressablesQuery(a, bson.M{TOPIC: t}) -} - -func (m *mongoDB) getAddressablesByPort(a *[]models.Addressable, p int) error { - return m.getAddressablesQuery(a, bson.M{PORT: p}) -} - -func (m *mongoDB) getAddressablesByPublisher(a *[]models.Addressable, p string) error { - return m.getAddressablesQuery(a, bson.M{PUBLISHER: p}) -} - -func (m *mongoDB) getAddressablesByAddress(a *[]models.Addressable, add string) error { - return m.getAddressablesQuery(a, bson.M{ADDRESS: add}) -} - -func (m *mongoDB) getAddressable(d *models.Addressable, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(ADDCOL) - err := col.Find(q).One(d) - if err != nil { - return err - } - - return nil -} - -func (m *mongoDB) deleteAddressable(a models.Addressable) error { - return m.deleteById(ADDCOL, a.Id.Hex()) -} - -/* ----------------------------- Device Service ----------------------------------*/ -func (m *mongoDB) getDeviceServiceByName(d *models.DeviceService, n string) error { - return m.getDeviceService(d, bson.M{NAME: n}) -} - -func (m *mongoDB) getDeviceServiceById(d *models.DeviceService, id string) error { - if bson.IsObjectIdHex(id) { - return m.getDeviceService(d, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetDeviceServiceByName Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getAllDeviceServices(d *[]models.DeviceService) error { - return m.getDeviceServices(d, bson.M{}) -} - -func (m *mongoDB) getDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error { - if bson.IsObjectIdHex(id) { - return m.getDeviceServices(d, bson.M{ADDRESSABLE + ".$id": bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetDeviceServicesByAddressableId Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error { - return m.getDeviceServices(d, bson.M{LABELS: bson.M{"$in": l}}) -} - -func (m *mongoDB) getDeviceServices(d *[]models.DeviceService, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DSCOL) - mdss := []MongoDeviceService{} - err := col.Find(q).Sort(QUERYTS).All(&mdss) - if err != nil { - return err - } - for _, mds := range mdss { - *d = append(*d, mds.DeviceService) - } - - return nil -} - -func (m *mongoDB) getDeviceService(d *models.DeviceService, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DSCOL) - mds := MongoDeviceService{} - err := col.Find(q).One(&mds) - if err != nil { - return err - } - *d = mds.DeviceService - - return nil -} - -func (m *mongoDB) addDeviceService(d *models.DeviceService) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(DSCOL) - - // check if the name exist - count, err := col.Find(bson.M{NAME: d.Service.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return ErrDuplicateName - } - - ts := makeTimestamp() - d.Service.Created = ts - d.Service.Modified = ts - d.Service.Id = bson.NewObjectId() - - // MongoDeviceService handles the DBRefs - mds := MongoDeviceService{DeviceService: *d} - return col.Insert(mds) -} - -func (m *mongoDB) updateDeviceService(deviceService models.DeviceService) error { - s := m.s.Copy() - defer s.Close() - c := s.DB(DB).C(DSCOL) - - deviceService.Service.Modified = makeTimestamp() - - // Handle DBRefs - mds := MongoDeviceService{DeviceService: deviceService} - - return c.UpdateId(deviceService.Service.Id, mds) -} - -func (m *mongoDB) deleteDeviceService(ds models.DeviceService) error { - return m.deleteById(DSCOL, ds.Id.Hex()) -} - -// ----------------------Provision Watcher -----------------------------*/ -func (m *mongoDB) getAllProvisionWatchers(pw *[]models.ProvisionWatcher) error { - return m.getProvisionWatchers(pw, bson.M{}) -} - -func (m *mongoDB) getProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error { - return m.getProvisionWatcher(pw, bson.M{NAME: n}) -} - -func (m *mongoDB) getProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error { - return m.getProvisionWatchers(pw, bson.M{IDENTIFIERS + "." + k: v}) -} - -func (m *mongoDB) getProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error { - if bson.IsObjectIdHex(id) { - return m.getProvisionWatchers(pw, bson.M{SERVICE + ".$id": bson.ObjectIdHex(id)}) - } else { - return errors.New("mgoGetProvisionWatchersByServiceId Invalid Object ID " + id) - } -} - -func (m *mongoDB) getProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error { - if bson.IsObjectIdHex(id) { - return m.getProvisionWatchers(pw, bson.M{PROFILE + ".$id": bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetProvisionWatcherByProfileId Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getProvisionWatcherById(pw *models.ProvisionWatcher, id string) error { - if bson.IsObjectIdHex(id) { - return m.getProvisionWatcher(pw, bson.M{_ID: bson.ObjectIdHex(id)}) - } else { - err := errors.New("mgoGetProvisionWatcherById Invalid Object ID " + id) - return err - } -} - -func (m *mongoDB) getProvisionWatcher(pw *models.ProvisionWatcher, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(PWCOL) - - // Handle DBRefs - var mpw MongoProvisionWatcher - - err := col.Find(q).One(&mpw) - if err != nil { - return err - } - - *pw = mpw.ProvisionWatcher - - return err -} - -func (m *mongoDB) getProvisionWatchers(pw *[]models.ProvisionWatcher, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(PWCOL) - - // Handle DBRefs - var mpws []MongoProvisionWatcher - - err := col.Find(q).Sort(QUERYTS).All(&mpws) - if err != nil { - return err - } - - for _, mpw := range mpws { - *pw = append(*pw, mpw.ProvisionWatcher) - } - - return nil -} - -func (m *mongoDB) addProvisionWatcher(pw *models.ProvisionWatcher) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(PWCOL) - count, err := col.Find(bson.M{NAME: pw.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return ErrDuplicateName - } - - // get Device Service - var dev models.DeviceService - if pw.Service.Service.Id.Hex() != "" { - m.getDeviceServiceById(&dev, pw.Service.Service.Id.Hex()) - } else if pw.Service.Service.Name != "" { - m.getDeviceServiceByName(&dev, pw.Service.Service.Name) - } else { - return errors.New("Device Service ID or Name is required") - } - pw.Service = dev - - // get Device Profile - var dp models.DeviceProfile - if pw.Profile.Id.Hex() != "" { - m.getDeviceProfileById(&dp, pw.Profile.Id.Hex()) - } else if pw.Profile.Name != "" { - m.getDeviceProfileByName(&dp, pw.Profile.Name) - } else { - return errors.New("Device Profile ID or Name is required") - } - pw.Profile = dp - - // Set data - ts := makeTimestamp() - pw.Created = ts - pw.Modified = ts - pw.Id = bson.NewObjectId() - - // Handle DBRefs - mpw := MongoProvisionWatcher{ProvisionWatcher: *pw} - - return col.Insert(mpw) -} - -func (m *mongoDB) updateProvisionWatcher(pw models.ProvisionWatcher) error { - s := m.s.Copy() - defer s.Close() - c := s.DB(DB).C(PWCOL) - - pw.Modified = makeTimestamp() - - // Handle DBRefs - mpw := MongoProvisionWatcher{ProvisionWatcher: pw} - - return c.UpdateId(mpw.Id, mpw) -} - -func (m *mongoDB) deleteProvisionWatcher(pw models.ProvisionWatcher) error { - return m.deleteById(PWCOL, pw.Id.Hex()) -} - -// ------------------------Command -------------------------------------*/ -func (m *mongoDB) getAllCommands(d *[]models.Command) error { - return m.getCommands(d, bson.M{}) -} - -func (m *mongoDB) getCommands(d *[]models.Command, q bson.M) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(COMCOL) - return col.Find(q).Sort(QUERYTS).All(d) -} - -func (m *mongoDB) getCommandById(d *models.Command, id string) error { - if bson.IsObjectIdHex(id) { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(COMCOL) - return col.Find(bson.M{_ID: bson.ObjectIdHex(id)}).One(d) - } else { - return errors.New("mgoGetCommandById Invalid Object ID " + id) - } -} - -func (m *mongoDB) getCommandByName(c *[]models.Command, n string) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(COMCOL) - return col.Find(bson.M{NAME: n}).All(c) -} - -func (m *mongoDB) addCommand(c *models.Command) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(COMCOL) - - ts := makeTimestamp() - c.Created = ts - c.Id = bson.NewObjectId() - return col.Insert(c) -} - -// Update command uses the ID of the command for identification -func (m *mongoDB) updateCommand(c *models.Command, r *models.Command) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(COMCOL) - if c == nil { - return nil - } - - // Check if the command has a valid ID - if len(c.Id.Hex()) == 0 || !bson.IsObjectIdHex(c.Id.Hex()) { - return errors.New("ID required for updating a command") - } - - // Update the fields - if c.Name != "" { - r.Name = c.Name - } - // TODO check for Get and Put Equality - - if (c.Get.String() != models.Get{}.String()) { - r.Get = c.Get - } - if (c.Put.String() != models.Put{}.String()) { - r.Put = c.Put - } - if c.Origin != 0 { - r.Origin = c.Origin - } - - return col.UpdateId(r.Id, r) -} - -// Delete the command by ID -// Check if the command is still in use by device profiles -func (m *mongoDB) deleteCommandById(id string) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(COMCOL) - - if !bson.IsObjectIdHex(id) { - return errors.New("Invalid ID") - } - - // Check if the command is still in use - query := bson.M{"commands": bson.M{"$elemMatch": bson.M{"_id": bson.ObjectIdHex(id)}}} - count, err := s.DB(DB).C(DPCOL).Find(query).Count() - if err != nil { - return err - } - if count > 0 { - return ErrCommandStillInUse - } - - return col.RemoveId(bson.ObjectIdHex(id)) -} - -func (m *mongoDB) deleteById(c string, did string) error { - if bson.IsObjectIdHex(did) { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(c) - err := col.RemoveId(bson.ObjectIdHex(did)) - if err != nil { - return err - } - - return nil - } else { - err := errors.New("Invalid object ID " + did) - return err - } -} - -func (m *mongoDB) deleteByName(c string, n string) error { - s := m.s.Copy() - defer s.Close() - col := s.DB(DB).C(c) - err := col.Remove(bson.M{NAME: n}) - if err != nil { - return err - } - - return nil -} diff --git a/core/metadata/rest_addressable.go b/core/metadata/rest_addressable.go index f7524f4a5f..2ed3285e91 100644 --- a/core/metadata/rest_addressable.go +++ b/core/metadata/rest_addressable.go @@ -20,6 +20,7 @@ import ( "net/url" "strconv" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" @@ -27,7 +28,7 @@ import ( func restGetAllAddressables(w http.ResponseWriter, _ *http.Request) { results := make([]models.Addressable, 0) - err := db.getAddressables(&results) + err := dbClient.GetAddressables(&results) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -62,9 +63,9 @@ func restAddAddressable(w http.ResponseWriter, r *http.Request) { } } - err = db.addAddressable(&a) + err = dbClient.AddAddressable(&a) if err != nil { - if err == ErrDuplicateName { + if err == db.ErrNotUnique { http.Error(w, "Duplicate name for addressable", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -93,10 +94,10 @@ func restUpdateAddressable(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var res models.Addressable - err := db.getAddressableById(&res, ra.Id.Hex()) + err := dbClient.GetAddressableById(&res, ra.Id.Hex()) if err != nil { if ra.Id == "" { - err = db.getAddressableByName(&res, ra.Name) + err = dbClient.GetAddressableByName(&res, ra.Name) } if err != nil { if err == mgo.ErrNotFound { @@ -125,7 +126,7 @@ func restUpdateAddressable(w http.ResponseWriter, r *http.Request) { } } - if err := db.updateAddressable(&ra, &res); err != nil { + if err := dbClient.UpdateAddressable(&ra, &res); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -146,7 +147,7 @@ func restGetAddressableById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var id string = vars["id"] var result models.Addressable - if err := db.getAddressableById(&result, id); err != nil { + if err := dbClient.GetAddressableById(&result, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -164,7 +165,7 @@ func restDeleteAddressableById(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err := db.getAddressableById(&a, id) + err := dbClient.GetAddressableById(&a, id) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -185,7 +186,7 @@ func restDeleteAddressableById(w http.ResponseWriter, r *http.Request) { return } - err = db.deleteAddressable(a) + err = dbClient.DeleteAddressable(a) if err != nil { if err == mgo.ErrNotFound { loggingClient.Error(err.Error(), "") @@ -214,7 +215,7 @@ func restDeleteAddressableByName(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err = db.getAddressableByName(&a, n) + err = dbClient.GetAddressableByName(&a, n) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -235,7 +236,7 @@ func restDeleteAddressableByName(w http.ResponseWriter, r *http.Request) { return } - if err := db.deleteAddressable(a); err != nil { + if err := dbClient.DeleteAddressable(a); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -256,7 +257,7 @@ func restDeleteAddressableByName(w http.ResponseWriter, r *http.Request) { func isAddressableStillInUse(a models.Addressable) (bool, error) { // Check devices var d []models.Device - err := db.getDevicesByAddressableId(&d, a.Id.Hex()) + err := dbClient.GetDevicesByAddressableId(&d, a.Id.Hex()) if err != nil { return false, err } @@ -266,7 +267,7 @@ func isAddressableStillInUse(a models.Addressable) (bool, error) { // Check device services var ds []models.DeviceService - err = db.getDeviceServicesByAddressableId(&ds, a.Id.Hex()) + err = dbClient.GetDeviceServicesByAddressableId(&ds, a.Id.Hex()) if err != nil { return false, err } @@ -285,7 +286,7 @@ func restGetAddressableByName(w http.ResponseWriter, r *http.Request) { return } var result models.Addressable - if err := db.getAddressableByName(&result, dn); err != nil { + if err := dbClient.GetAddressableByName(&result, dn); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -309,7 +310,7 @@ func restGetAddressableByTopic(w http.ResponseWriter, r *http.Request) { } res := make([]models.Addressable, 0) - err = db.getAddressablesByTopic(&res, t) + err = dbClient.GetAddressablesByTopic(&res, t) if err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { @@ -334,7 +335,7 @@ func restGetAddressableByPort(w http.ResponseWriter, r *http.Request) { } res := make([]models.Addressable, 0) - if err := db.getAddressablesByPort(&res, p); err != nil { + if err := dbClient.GetAddressablesByPort(&res, p); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -352,7 +353,7 @@ func restGetAddressableByPublisher(w http.ResponseWriter, r *http.Request) { return } res := make([]models.Addressable, 0) - err = db.getAddressablesByPublisher(&res, p) + err = dbClient.GetAddressablesByPublisher(&res, p) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -371,7 +372,7 @@ func restGetAddressableByAddress(w http.ResponseWriter, r *http.Request) { return } res := make([]models.Addressable, 0) - err = db.getAddressablesByAddress(&res, a) + err = dbClient.GetAddressablesByAddress(&res, a) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -385,7 +386,7 @@ func restGetAddressableByAddress(w http.ResponseWriter, r *http.Request) { // Notify the associated device services for the addressable func notifyAddressableAssociates(a models.Addressable, action string) error { var ds []models.DeviceService - if err := db.getDeviceServicesByAddressableId(&ds, a.Id.Hex()); err != nil { + if err := dbClient.GetDeviceServicesByAddressableId(&ds, a.Id.Hex()); err != nil { loggingClient.Error(err.Error(), "") return err } diff --git a/core/metadata/rest_command.go b/core/metadata/rest_command.go index 31e2ac3cd0..0f14fa92e8 100644 --- a/core/metadata/rest_command.go +++ b/core/metadata/rest_command.go @@ -19,6 +19,7 @@ import ( "net/http" "net/url" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" @@ -26,7 +27,7 @@ import ( func restGetAllCommands(w http.ResponseWriter, _ *http.Request) { results := make([]models.Command, 0) - err := db.getAllCommands(&results) + err := dbClient.GetAllCommands(&results) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusInternalServerError) @@ -52,7 +53,7 @@ func restAddCommand(w http.ResponseWriter, r *http.Request) { return } - if err := db.addCommand(&c); err != nil { + if err := dbClient.AddCommand(&c); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -76,7 +77,7 @@ func restUpdateCommand(w http.ResponseWriter, r *http.Request) { } // Check if command exists (By ID) - err := db.getCommandById(&res, c.Id.Hex()) + err := dbClient.GetCommandById(&res, c.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -86,7 +87,7 @@ func restUpdateCommand(w http.ResponseWriter, r *http.Request) { // Name is changed, make sure the new name doesn't conflict with device profile if c.Name != "" { var dp []models.DeviceProfile - err = db.getDeviceProfilesUsingCommand(&dp, c) + err = dbClient.GetDeviceProfilesUsingCommand(&dp, c) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -106,7 +107,7 @@ func restUpdateCommand(w http.ResponseWriter, r *http.Request) { } } - if err := db.updateCommand(&c, &res); err != nil { + if err := dbClient.UpdateCommand(&c, &res); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -120,9 +121,9 @@ func restGetCommandById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.Command - err := db.getCommandById(&res, did) + err := dbClient.GetCommandById(&res, did) if err != nil { - if err == ErrNotFound { + if err == db.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -144,7 +145,7 @@ func restGetCommandByName(w http.ResponseWriter, r *http.Request) { return } results := []models.Command{} - err = db.getCommandByName(&results, n) + err = dbClient.GetCommandByName(&results, n) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -162,7 +163,7 @@ func restDeleteCommandById(w http.ResponseWriter, r *http.Request) { // Check if the command exists var c models.Command - err := db.getCommandById(&c, id) + err := dbClient.GetCommandById(&c, id) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -183,11 +184,11 @@ func restDeleteCommandById(w http.ResponseWriter, r *http.Request) { return } - if err := db.deleteCommandById(id); err != nil { + if err := dbClient.DeleteCommandById(id); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) - } else if err == ErrCommandStillInUse { + } else if err == db.ErrCommandStillInUse { http.Error(w, err.Error(), http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -202,7 +203,7 @@ func restDeleteCommandById(w http.ResponseWriter, r *http.Request) { // Helper function to determine if the command is still in use by device profiles func isCommandStillInUse(c models.Command) (bool, error) { var dp []models.DeviceProfile - err := db.getDeviceProfilesUsingCommand(&dp, c) + err := dbClient.GetDeviceProfilesUsingCommand(&dp, c) if err != nil { return false, err } diff --git a/core/metadata/rest_device.go b/core/metadata/rest_device.go index 6559b911f6..3045daa5b4 100644 --- a/core/metadata/rest_device.go +++ b/core/metadata/rest_device.go @@ -16,12 +16,13 @@ package metadata import ( "encoding/json" "errors" + "fmt" "net/http" "net/url" "strconv" "time" - "fmt" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" notifications "github.com/edgexfoundry/edgex-go/support/notifications-client" "github.com/gorilla/mux" @@ -31,7 +32,7 @@ import ( func restGetAllDevices(w http.ResponseWriter, _ *http.Request) { res := make([]models.Device, 0) - err := db.getAllDevices(&res) + err := dbClient.GetAllDevices(&res) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -67,10 +68,10 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { // Addressable check // Try by name - err = db.getAddressableByName(&d.Addressable, d.Addressable.Name) + err = dbClient.GetAddressableByName(&d.Addressable, d.Addressable.Name) if err != nil { // Try by ID - err = db.getAddressableById(&d.Addressable, d.Addressable.Id.Hex()) + err = dbClient.GetAddressableById(&d.Addressable, d.Addressable.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error()+": A device must be associated to an Addressable", http.StatusConflict) @@ -80,10 +81,10 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { // Service Check // Try by name - err = db.getDeviceServiceByName(&d.Service, d.Service.Service.Name) + err = dbClient.GetDeviceServiceByName(&d.Service, d.Service.Service.Name) if err != nil { // Try by ID - err = db.getDeviceServiceById(&d.Service, d.Service.Service.Id.Hex()) + err = dbClient.GetDeviceServiceById(&d.Service, d.Service.Service.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error()+": A device must be associated with a device service", http.StatusConflict) @@ -93,10 +94,10 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { // Profile Check // Try by name - err = db.getDeviceProfileByName(&d.Profile, d.Profile.Name) + err = dbClient.GetDeviceProfileByName(&d.Profile, d.Profile.Name) if err != nil { // Try by ID - err = db.getDeviceProfileById(&d.Profile, d.Profile.Id.Hex()) + err = dbClient.GetDeviceProfileById(&d.Profile, d.Profile.Id.Hex()) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error()+": A device must be associated with a device profile", http.StatusConflict) @@ -113,9 +114,9 @@ func restAddNewDevice(w http.ResponseWriter, r *http.Request) { } // Add the device - err = db.addDevice(&d) + err = dbClient.AddDevice(&d) if err != nil { - if err == ErrDuplicateName { + if err == db.ErrNotUnique { http.Error(w, "Duplicate name for device", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -147,10 +148,10 @@ func restUpdateDevice(w http.ResponseWriter, r *http.Request) { // Check if the device exists var oldDevice models.Device // First try ID - err = db.getDeviceById(&oldDevice, rd.Id.Hex()) + err = dbClient.GetDeviceById(&oldDevice, rd.Id.Hex()) if err != nil { // Then try name - err = db.getDeviceByName(&oldDevice, rd.Name) + err = dbClient.GetDeviceByName(&oldDevice, rd.Name) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -164,7 +165,7 @@ func restUpdateDevice(w http.ResponseWriter, r *http.Request) { return } - if err = db.updateDevice(oldDevice); err != nil { + if err = dbClient.UpdateDevice(oldDevice); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -183,10 +184,10 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the new addressable exists var a models.Addressable // Try ID first - err := db.getAddressableById(&a, from.Addressable.Id.Hex()) + err := dbClient.GetAddressableById(&a, from.Addressable.Id.Hex()) if err != nil { // Then try name - err = db.getAddressableByName(&a, from.Addressable.Name) + err = dbClient.GetAddressableByName(&a, from.Addressable.Name) if err != nil { return errors.New("Addressable not found for updated device") } @@ -198,10 +199,10 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the new service exists var ds models.DeviceService // Try ID first - err := db.getDeviceServiceById(&ds, from.Service.Service.Id.Hex()) + err := dbClient.GetDeviceServiceById(&ds, from.Service.Service.Id.Hex()) if err != nil { // Then try name - err = db.getDeviceServiceByName(&ds, from.Service.Service.Name) + err = dbClient.GetDeviceServiceByName(&ds, from.Service.Service.Name) if err != nil { return errors.New("Device service not found for updated device") } @@ -213,10 +214,10 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the new profile exists var dp models.DeviceProfile // Try ID first - err := db.getDeviceProfileById(&dp, from.Profile.Id.Hex()) + err := dbClient.GetDeviceProfileById(&dp, from.Profile.Id.Hex()) if err != nil { // Then try Name - err = db.getDeviceProfileByName(&dp, from.Profile.Name) + err = dbClient.GetDeviceProfileByName(&dp, from.Profile.Name) if err != nil { return errors.New("Device profile not found for updated device") } @@ -253,7 +254,7 @@ func updateDeviceFields(from models.Device, to *models.Device) error { // Check if the name is unique var checkD models.Device - err := db.getDeviceByName(&checkD, from.Name) + err := dbClient.GetDeviceByName(&checkD, from.Name) if err != nil { // A problem occured accessing database if err != mgo.ErrNotFound { @@ -289,7 +290,7 @@ func restGetDevicesWithLabel(w http.ResponseWriter, r *http.Request) { labels = append(labels, label) res := make([]models.Device, 0) - err = db.getDevicesWithLabel(&res, labels) + err = dbClient.GetDevicesWithLabel(&res, labels) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -306,7 +307,7 @@ func restGetDeviceByProfileId(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - err := db.getDeviceProfileById(&dp, pid) + err := dbClient.GetDeviceProfileById(&dp, pid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -318,7 +319,7 @@ func restGetDeviceByProfileId(w http.ResponseWriter, r *http.Request) { } res := make([]models.Device, 0) - err = db.getDevicesByProfileId(&res, pid) + err = dbClient.GetDevicesByProfileId(&res, pid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -336,7 +337,7 @@ func restGetDeviceByServiceId(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - err := db.getDeviceServiceById(&ds, sid) + err := dbClient.GetDeviceServiceById(&ds, sid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -347,7 +348,7 @@ func restGetDeviceByServiceId(w http.ResponseWriter, r *http.Request) { return } - err = db.getDevicesByServiceId(&res, sid) + err = dbClient.GetDevicesByServiceId(&res, sid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -370,7 +371,7 @@ func restGetDeviceByServiceName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - err = db.getDeviceServiceByName(&ds, sn) + err = dbClient.GetDeviceServiceByName(&ds, sn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -384,7 +385,7 @@ func restGetDeviceByServiceName(w http.ResponseWriter, r *http.Request) { res := make([]models.Device, 0) // Find devices by service ID now that you have the Service object (and therefor the ID) - err = db.getDevicesByServiceId(&res, ds.Service.Id.Hex()) + err = dbClient.GetDevicesByServiceId(&res, ds.Service.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -406,7 +407,7 @@ func restGetDeviceByAddressableName(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err = db.getAddressableByName(&a, an) + err = dbClient.GetAddressableByName(&a, an) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -420,7 +421,7 @@ func restGetDeviceByAddressableName(w http.ResponseWriter, r *http.Request) { res := make([]models.Device, 0) // Use the addressable ID now that you have the addressable object - err = db.getDevicesByAddressableId(&res, a.Id.Hex()) + err = dbClient.GetDevicesByAddressableId(&res, a.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -442,7 +443,7 @@ func restGetDeviceByProfileName(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - err = db.getDeviceProfileByName(&dp, pn) + err = dbClient.GetDeviceProfileByName(&dp, pn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -456,7 +457,7 @@ func restGetDeviceByProfileName(w http.ResponseWriter, r *http.Request) { res := make([]models.Device, 0) // Use profile ID now that you have the profile object - err = db.getDevicesByProfileId(&res, dp.Id.Hex()) + err = dbClient.GetDevicesByProfileId(&res, dp.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -473,7 +474,7 @@ func restGetDeviceByAddressableId(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - err := db.getAddressableById(&a, aid) + err := dbClient.GetAddressableById(&a, aid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -485,7 +486,7 @@ func restGetDeviceByAddressableId(w http.ResponseWriter, r *http.Request) { } res := make([]models.Device, 0) - err = db.getDevicesByAddressableId(&res, aid) + err = dbClient.GetDevicesByAddressableId(&res, aid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -500,7 +501,7 @@ func restGetDeviceById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.Device - if err := db.getDeviceById(&res, did); err != nil { + if err := dbClient.GetDeviceById(&res, did); err != nil { loggingClient.Error(err.Error(), "") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -519,7 +520,7 @@ func restCheckForDevice(w http.ResponseWriter, r *http.Request) { token := vars[ID] //referring to this as "token" for now since the source variable is double purposed dev := models.Device{} //Check for name first since we're using that meaning by default. - if err := db.getDeviceByName(&dev, token); err != nil { + if err := dbClient.GetDeviceByName(&dev, token); err != nil { if err != mgo.ErrNotFound { loggingClient.Error(err.Error(), "restCheckForDevice") http.Error(w, err.Error(), http.StatusInternalServerError) @@ -531,7 +532,7 @@ func restCheckForDevice(w http.ResponseWriter, r *http.Request) { //If lookup by name failed, see if we were passed the ID if len(dev.Name) == 0 { if bson.IsObjectIdHex(token) { - if err := db.getDeviceById(&dev, token); err != nil { + if err := dbClient.GetDeviceById(&dev, token); err != nil { loggingClient.Error(err.Error(), "restCheckForDevice") if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -564,7 +565,7 @@ func restSetDeviceOpStateById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err := db.getDeviceById(&d, did) + err := dbClient.GetDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -577,7 +578,7 @@ func restSetDeviceOpStateById(w http.ResponseWriter, r *http.Request) { // Update OpState d.OperatingState = newOs - if err = db.updateDevice(d); err != nil { + if err = dbClient.UpdateDevice(d); err != nil { return } if err != nil { @@ -614,7 +615,7 @@ func restSetDeviceOpStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -627,7 +628,7 @@ func restSetDeviceOpStateByName(w http.ResponseWriter, r *http.Request) { // Update OpState d.OperatingState = newOs - if err = db.updateDevice(d); err != nil { + if err = dbClient.UpdateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -654,7 +655,7 @@ func restSetDeviceAdminStateById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err := db.getDeviceById(&d, did) + err := dbClient.GetDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -667,7 +668,7 @@ func restSetDeviceAdminStateById(w http.ResponseWriter, r *http.Request) { // Update the AdminState d.AdminState = newAs - if err = db.updateDevice(d); err != nil { + if err = dbClient.UpdateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -704,7 +705,7 @@ func restSetDeviceAdminStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -717,7 +718,7 @@ func restSetDeviceAdminStateByName(w http.ResponseWriter, r *http.Request) { d.AdminState = newAs // Update the admin state - if err = db.updateDevice(d); err != nil { + if err = dbClient.UpdateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -741,7 +742,7 @@ func restDeleteDeviceById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device //err := getDeviceById(&d, did) - if err := db.getDeviceById(&d, did); err != nil { + if err := dbClient.GetDeviceById(&d, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -770,7 +771,7 @@ func restDeleteDeviceByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -793,7 +794,7 @@ func deleteDevice(d models.Device, w http.ResponseWriter) error { return err } - if err := db.deleteDevice(d); err != nil { + if err := dbClient.DeleteDevice(d); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -810,7 +811,7 @@ func deleteDevice(d models.Device, w http.ResponseWriter) error { // Delete the associated device reports for the device func deleteAssociatedReportsForDevice(d models.Device, w http.ResponseWriter) error { var reports []models.DeviceReport - if err := db.getDeviceReportByDeviceName(&reports, d.Name); err != nil { + if err := dbClient.GetDeviceReportByDeviceName(&reports, d.Name); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return err @@ -818,7 +819,7 @@ func deleteAssociatedReportsForDevice(d models.Device, w http.ResponseWriter) er // Delete the associated reports for _, report := range reports { - if err := db.deleteDeviceReport(report); err != nil { + if err := dbClient.DeleteDeviceReport(report); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return err @@ -842,7 +843,7 @@ func restSetDeviceLastConnectedById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceById(&d, did) + err = dbClient.GetDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -882,7 +883,7 @@ func restSetLastConnectedByIdNotify(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceById(&d, did) + err = dbClient.GetDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -920,7 +921,7 @@ func restSetDeviceLastConnectedByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -964,7 +965,7 @@ func restSetDeviceLastConnectedByNameNotify(w http.ResponseWriter, r *http.Reque // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -987,7 +988,7 @@ func restSetDeviceLastConnectedByNameNotify(w http.ResponseWriter, r *http.Reque // Update the last connected value for the device func setLastConnected(d models.Device, time int64, notify bool, w http.ResponseWriter) error { d.LastConnected = time - if err := db.updateDevice(d); err != nil { + if err := dbClient.UpdateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return err @@ -1013,7 +1014,7 @@ func restSetDeviceLastReportedById(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceById(&d, did) + err = dbClient.GetDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1052,7 +1053,7 @@ func restSetDeviceLastReportedByIdNotify(w http.ResponseWriter, r *http.Request) // Check if the device exists var d models.Device - err = db.getDeviceById(&d, did) + err = dbClient.GetDeviceById(&d, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1090,7 +1091,7 @@ func restSetDeviceLastReportedByName(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1134,7 +1135,7 @@ func restSetDeviceLastReportedByNameNotify(w http.ResponseWriter, r *http.Reques // Check if the device exists var d models.Device - err = db.getDeviceByName(&d, n) + err = dbClient.GetDeviceByName(&d, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1157,7 +1158,7 @@ func restSetDeviceLastReportedByNameNotify(w http.ResponseWriter, r *http.Reques // Update the last reported field of the device func setLastReported(d models.Device, time int64, notify bool, w http.ResponseWriter) error { d.LastReported = time - if err := db.updateDevice(d); err != nil { + if err := dbClient.UpdateDevice(d); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return err @@ -1179,7 +1180,7 @@ func restGetDeviceByName(w http.ResponseWriter, r *http.Request) { return } var res models.Device - err = db.getDeviceByName(&res, dn) + err = dbClient.GetDeviceByName(&res, dn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -1200,7 +1201,7 @@ func notifyDeviceAssociates(d models.Device, action string) error { // Callback for device service var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { loggingClient.Error(err.Error(), "") return err } diff --git a/core/metadata/rest_deviceprofile.go b/core/metadata/rest_deviceprofile.go index 5fc5493c9a..ee3a814efe 100644 --- a/core/metadata/rest_deviceprofile.go +++ b/core/metadata/rest_deviceprofile.go @@ -20,6 +20,7 @@ import ( "net/http" "net/url" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" @@ -28,7 +29,7 @@ import ( func restGetAllDeviceProfiles(w http.ResponseWriter, _ *http.Request) { res := []models.DeviceProfile{} - if err := db.getAllDeviceProfiles(&res); err != nil { + if err := dbClient.GetAllDeviceProfiles(&res); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -70,8 +71,8 @@ func restAddDeviceProfile(w http.ResponseWriter, r *http.Request) { } } - if err := db.addDeviceProfile(&dp); err != nil { - if err == ErrDuplicateName { + if err := dbClient.AddDeviceProfile(&dp); err != nil { + if err == db.ErrNotUnique { http.Error(w, "Duplicate name for device profile", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -97,10 +98,10 @@ func restUpdateDeviceProfile(w http.ResponseWriter, r *http.Request) { // Check if the Device Profile exists var to models.DeviceProfile // First try with ID - err := db.getDeviceProfileById(&to, from.Id.Hex()) + err := dbClient.GetDeviceProfileById(&to, from.Id.Hex()) if err != nil { // Try with name - err = db.getDeviceProfileByName(&to, from.Name) + err = dbClient.GetDeviceProfileByName(&to, from.Name) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) @@ -113,7 +114,7 @@ func restUpdateDeviceProfile(w http.ResponseWriter, r *http.Request) { loggingClient.Error(err.Error(), "") return } - if err := db.updateDeviceProfile(&to); err != nil { + if err := dbClient.UpdateDeviceProfile(&to); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -187,7 +188,7 @@ func updateDeviceProfileFields(from models.DeviceProfile, to *models.DeviceProfi // Check for duplicate names in device profiles func checkDuplicateProfileNames(dp models.DeviceProfile, w http.ResponseWriter) error { profiles := []models.DeviceProfile{} - if err := db.getAllDeviceProfiles(&profiles); err != nil { + if err := dbClient.GetAllDeviceProfiles(&profiles); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -226,7 +227,7 @@ func checkDuplicateCommands(dp models.DeviceProfile, w http.ResponseWriter) erro // Delete all of the commands that are a part of the device profile func deleteCommands(dp models.DeviceProfile, w http.ResponseWriter) error { for _, command := range dp.Commands { - err := db.deleteCommandById(command.Id.Hex()) + err := dbClient.DeleteCommandById(command.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err @@ -239,7 +240,7 @@ func deleteCommands(dp models.DeviceProfile, w http.ResponseWriter) error { // Add all of the commands that are a part of the device profile func addCommands(dp *models.DeviceProfile, w http.ResponseWriter) error { for i := range dp.Commands { - if err := db.addCommand(&(dp.Commands[i])); err != nil { + if err := dbClient.AddCommand(&(dp.Commands[i])); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -252,7 +253,7 @@ func restGetProfileByProfileId(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars["id"] var res models.DeviceProfile - if err := db.getDeviceProfileById(&res, did); err != nil { + if err := dbClient.GetDeviceProfileById(&res, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -271,7 +272,7 @@ func restDeleteProfileByProfileId(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - if err := db.getDeviceProfileById(&dp, did); err != nil { + if err := dbClient.GetDeviceProfileById(&dp, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -303,7 +304,7 @@ func restDeleteProfileByName(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - if err = db.getDeviceProfileByName(&dp, n); err != nil { + if err = dbClient.GetDeviceProfileByName(&dp, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -329,7 +330,7 @@ func restDeleteProfileByName(w http.ResponseWriter, r *http.Request) { func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { // Check if the device profile is still in use by devices var d []models.Device - if err := db.getDevicesByProfileId(&d, dp.Id.Hex()); err != nil { + if err := dbClient.GetDevicesByProfileId(&d, dp.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -341,7 +342,7 @@ func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { // Check if the device profile is still in use by provision watchers var pw []models.ProvisionWatcher - if err := db.getProvisionWatcherByProfileId(&pw, dp.Id.Hex()); err != nil { + if err := dbClient.GetProvisionWatcherByProfileId(&pw, dp.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -352,7 +353,7 @@ func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { } // Delete the profile - if err := db.deleteDeviceProfile(dp); err != nil { + if err := dbClient.DeleteDeviceProfile(dp); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -430,8 +431,8 @@ func addDeviceProfileYaml(data []byte, w http.ResponseWriter) { } } - if err := db.addDeviceProfile(&dp); err != nil { - if err == ErrDuplicateName { + if err := dbClient.AddDeviceProfile(&dp); err != nil { + if err == db.ErrNotUnique { http.Error(w, "Duplicate profile name", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -454,7 +455,7 @@ func restGetProfileByModel(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceProfile, 0) - if err := db.getDeviceProfilesByModel(&res, an); err != nil { + if err := dbClient.GetDeviceProfilesByModel(&res, an); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -476,7 +477,7 @@ func restGetProfileWithLabel(w http.ResponseWriter, r *http.Request) { var labels []string labels = append(labels, label) res := make([]models.DeviceProfile, 0) - if err := db.getDeviceProfilesWithLabel(&res, labels); err != nil { + if err := dbClient.GetDeviceProfilesWithLabel(&res, labels); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -503,7 +504,7 @@ func restGetProfileByManufacturerModel(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceProfile, 0) - if err := db.getDeviceProfilesByManufacturerModel(&res, man, mod); err != nil { + if err := dbClient.GetDeviceProfilesByManufacturerModel(&res, man, mod); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -523,7 +524,7 @@ func restGetProfileByManufacturer(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceProfile, 0) - if err := db.getDeviceProfilesByManufacturer(&res, man); err != nil { + if err := dbClient.GetDeviceProfilesByManufacturer(&res, man); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -544,7 +545,7 @@ func restGetProfileByName(w http.ResponseWriter, r *http.Request) { // Get the device var res models.DeviceProfile - if err := db.getDeviceProfileByName(&res, dn); err != nil { + if err := dbClient.GetDeviceProfileByName(&res, dn); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -569,7 +570,7 @@ func restGetYamlProfileByName(w http.ResponseWriter, r *http.Request) { // Check for the device profile var dp models.DeviceProfile - err = db.getDeviceProfileByName(&dp, name) + err = dbClient.GetDeviceProfileByName(&dp, name) if err != nil { // Not found, return nil if err == mgo.ErrNotFound { @@ -607,7 +608,7 @@ func restGetYamlProfileById(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists var dp models.DeviceProfile - err := db.getDeviceProfileById(&dp, id) + err := dbClient.GetDeviceProfileById(&dp, id) if err != nil { if err == mgo.ErrNotFound { w.WriteHeader(http.StatusNotFound) @@ -636,7 +637,7 @@ func restGetYamlProfileById(w http.ResponseWriter, r *http.Request) { func notifyProfileAssociates(dp models.DeviceProfile, action string) error { // Get the devices var d []models.Device - if err := db.getDevicesByProfileId(&d, dp.Id.Hex()); err != nil { + if err := dbClient.GetDevicesByProfileId(&d, dp.Id.Hex()); err != nil { loggingClient.Error(err.Error(), "") return err } diff --git a/core/metadata/rest_devicereport.go b/core/metadata/rest_devicereport.go index 16e33f51f4..8174dc7ef2 100644 --- a/core/metadata/rest_devicereport.go +++ b/core/metadata/rest_devicereport.go @@ -19,6 +19,7 @@ import ( "net/http" "net/url" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" mgo "gopkg.in/mgo.v2" @@ -26,7 +27,7 @@ import ( func restGetAllDeviceReports(w http.ResponseWriter, _ *http.Request) { res := make([]models.DeviceReport, 0) - err := db.getAllDeviceReports(&res) + err := dbClient.GetAllDeviceReports(&res) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -59,7 +60,7 @@ func restAddDeviceReport(w http.ResponseWriter, r *http.Request) { // Check if the device exists var d models.Device - if err := db.getDeviceByName(&d, dr.Device); err != nil { + if err := dbClient.GetDeviceByName(&d, dr.Device); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device referenced by Device Report doesn't exist", http.StatusNotFound) } else { @@ -71,7 +72,7 @@ func restAddDeviceReport(w http.ResponseWriter, r *http.Request) { // Check if the Schedule Event exists var se models.ScheduleEvent - if err := db.getScheduleEventByName(&se, dr.Event); err != nil { + if err := dbClient.GetScheduleEventByName(&se, dr.Event); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule Event referenced by Device Report doesn't exist", http.StatusNotFound) } else { @@ -82,8 +83,8 @@ func restAddDeviceReport(w http.ResponseWriter, r *http.Request) { } // Add the device report - if err := db.addDeviceReport(&dr); err != nil { - if err == ErrDuplicateName { + if err := dbClient.AddDeviceReport(&dr); err != nil { + if err == db.ErrNotUnique { http.Error(w, "Duplicate Name for the device report", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -113,9 +114,9 @@ func restUpdateDeviceReport(w http.ResponseWriter, r *http.Request) { // Check if the device report exists var to models.DeviceReport // First try ID - if err := db.getDeviceReportById(&to, from.Id.Hex()); err != nil { + if err := dbClient.GetDeviceReportById(&to, from.Id.Hex()); err != nil { // Try by name - if err = db.getDeviceReportByName(&to, from.Name); err != nil { + if err = dbClient.GetDeviceReportByName(&to, from.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -131,7 +132,7 @@ func restUpdateDeviceReport(w http.ResponseWriter, r *http.Request) { return } - if err := db.updateDeviceReport(&to); err != nil { + if err := dbClient.UpdateDeviceReport(&to); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -177,7 +178,7 @@ func updateDeviceReportFields(from models.DeviceReport, to *models.DeviceReport, // Validate that the device exists func validateDevice(d string, w http.ResponseWriter) error { var device models.Device - if err := db.getDeviceByName(&device, d); err != nil { + if err := dbClient.GetDeviceByName(&device, d); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device was not found", http.StatusNotFound) } else { @@ -192,7 +193,7 @@ func validateDevice(d string, w http.ResponseWriter) error { // Validate that the schedule event exists func validateEvent(e string, w http.ResponseWriter) error { var event models.ScheduleEvent - if err := db.getScheduleEventByName(&event, e); err != nil { + if err := dbClient.GetScheduleEventByName(&event, e); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Event was not found", http.StatusNotFound) } else { @@ -208,7 +209,7 @@ func restGetReportById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.DeviceReport - err := db.getDeviceReportById(&res, did) + err := dbClient.GetDeviceReportById(&res, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -233,7 +234,7 @@ func restGetReportByName(w http.ResponseWriter, r *http.Request) { } var res models.DeviceReport - err = db.getDeviceReportByName(&res, n) + err = dbClient.GetDeviceReportByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -261,7 +262,7 @@ func restGetValueDescriptorsForDeviceName(w http.ResponseWriter, r *http.Request // Get all the associated device reports var reports []models.DeviceReport - if err = db.getDeviceReportByDeviceName(&reports, n); err != nil { + if err = dbClient.GetDeviceReportByDeviceName(&reports, n); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -287,7 +288,7 @@ func restGetDeviceReportByDeviceName(w http.ResponseWriter, r *http.Request) { } res := make([]models.DeviceReport, 0) - err = db.getDeviceReportByDeviceName(&res, n) + err = dbClient.GetDeviceReportByDeviceName(&res, n) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") @@ -304,7 +305,7 @@ func restDeleteReportById(w http.ResponseWriter, r *http.Request) { // Check if the device report exists var dr models.DeviceReport - if err := db.getDeviceReportById(&dr, id); err != nil { + if err := dbClient.GetDeviceReportById(&dr, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -334,7 +335,7 @@ func restDeleteReportByName(w http.ResponseWriter, r *http.Request) { // Check if the device report exists var dr models.DeviceReport - if err = db.getDeviceReportByName(&dr, n); err != nil { + if err = dbClient.GetDeviceReportByName(&dr, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -354,7 +355,7 @@ func restDeleteReportByName(w http.ResponseWriter, r *http.Request) { } func deleteDeviceReport(dr models.DeviceReport, w http.ResponseWriter) error { - if err := db.deleteDeviceReport(dr); err != nil { + if err := dbClient.DeleteDeviceReport(dr); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -371,13 +372,13 @@ func deleteDeviceReport(dr models.DeviceReport, w http.ResponseWriter) error { func notifyDeviceReportAssociates(dr models.DeviceReport, action string) error { // Get the device of the report var d models.Device - if err := db.getDeviceByName(&d, dr.Device); err != nil { + if err := dbClient.GetDeviceByName(&d, dr.Device); err != nil { return err } // Get the device service for the device var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, d.Service.Service.Id.Hex()); err != nil { return err } diff --git a/core/metadata/rest_deviceservice.go b/core/metadata/rest_deviceservice.go index 60fa3db1e1..165633b0ac 100644 --- a/core/metadata/rest_deviceservice.go +++ b/core/metadata/rest_deviceservice.go @@ -21,6 +21,7 @@ import ( "net/url" "strconv" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" @@ -33,9 +34,9 @@ func getAddressableByIdOrName(a *models.Addressable, w http.ResponseWriter) erro name := a.Name // Try by ID - if err := db.getAddressableById(a, id.Hex()); err != nil { + if err := dbClient.GetAddressableById(a, id.Hex()); err != nil { // Try by name - if err = db.getAddressableByName(a, name); err != nil { + if err = dbClient.GetAddressableByName(a, name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found", http.StatusServiceUnavailable) } else { @@ -50,7 +51,7 @@ func getAddressableByIdOrName(a *models.Addressable, w http.ResponseWriter) erro func restGetAllDeviceServices(w http.ResponseWriter, _ *http.Request) { r := make([]models.DeviceService, 0) - if err := db.getAllDeviceServices(&r); err != nil { + if err := dbClient.GetAllDeviceServices(&r); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -89,7 +90,7 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { var foundAddressable = false // First try by name - err = db.getAddressableByName(&ds.Service.Addressable, ds.Service.Addressable.Name) + err = dbClient.GetAddressableByName(&ds.Service.Addressable, ds.Service.Addressable.Name) if err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -102,7 +103,7 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { // Then try by ID if !foundAddressable { - err := db.getAddressableById(&ds.Service.Addressable, ds.Service.Addressable.Id.Hex()) + err := dbClient.GetAddressableById(&ds.Service.Addressable, ds.Service.Addressable.Id.Hex()) if err != nil { http.Error(w, "Addressable not found by ID or Name", http.StatusNotFound) loggingClient.Error("Addressable not found by ID or Name: "+err.Error(), "") @@ -114,8 +115,8 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { } // Add the device service - if err := db.addDeviceService(&ds); err != nil { - if err == ErrDuplicateName { + if err := dbClient.AddDeviceService(&ds); err != nil { + if err == db.ErrNotUnique { http.Error(w, "Duplicate name for the device service", http.StatusConflict) } else { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -136,7 +137,7 @@ func restGetAddressablesForAssociatedDevicesById(w http.ResponseWriter, r *http. var ds models.DeviceService // Check if the device service exists - if err := db.getDeviceServiceById(&ds, id); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -170,7 +171,7 @@ func restGetAddressablesForAssociatedDevicesByName(w http.ResponseWriter, r *htt // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, n); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -195,7 +196,7 @@ func restGetAddressablesForAssociatedDevicesByName(w http.ResponseWriter, r *htt func getAddressablesForAssociatedDevices(addressables *[]models.Addressable, ds models.DeviceService, w http.ResponseWriter) error { // Get the associated devices var devices []models.Device - if err := db.getDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { + if err := dbClient.GetDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -228,9 +229,9 @@ func restUpdateDeviceService(w http.ResponseWriter, r *http.Request) { // Check if the device service exists and get it var to models.DeviceService // Try by ID - if err = db.getDeviceServiceById(&to, from.Service.Id.Hex()); err != nil { + if err = dbClient.GetDeviceServiceById(&to, from.Service.Id.Hex()); err != nil { // Try by Name - if err = db.getDeviceServiceByName(&to, from.Service.Name); err != nil { + if err = dbClient.GetDeviceServiceByName(&to, from.Service.Name); err != nil { http.Error(w, "Device service not found", http.StatusNotFound) loggingClient.Error(err.Error(), "") return @@ -242,7 +243,7 @@ func restUpdateDeviceService(w http.ResponseWriter, r *http.Request) { return } - if err := db.updateDeviceService(to); err != nil { + if err := dbClient.UpdateDeviceService(to); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -287,7 +288,7 @@ func updateDeviceServiceFields(from models.DeviceService, to *models.DeviceServi // Check if the new name is unique var checkDS models.DeviceService - err := db.getDeviceServiceByName(&checkDS, from.Service.Name) + err := dbClient.GetDeviceServiceByName(&checkDS, from.Service.Name) if err != nil { // A problem occured accessing database if err != mgo.ErrNotFound { @@ -335,7 +336,7 @@ func restGetServiceByAddressableName(w http.ResponseWriter, r *http.Request) { // Check if the addressable exists var a models.Addressable - if err = db.getAddressableByName(&a, an); err != nil { + if err = dbClient.GetAddressableByName(&a, an); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found", http.StatusNotFound) } else { @@ -345,7 +346,7 @@ func restGetServiceByAddressableName(w http.ResponseWriter, r *http.Request) { return } - if err = db.getDeviceServicesByAddressableId(&res, a.Id.Hex()); err != nil { + if err = dbClient.GetDeviceServicesByAddressableId(&res, a.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return @@ -362,7 +363,7 @@ func restGetServiceByAddressableId(w http.ResponseWriter, r *http.Request) { // Check if the Addressable exists var a models.Addressable - if err := db.getAddressableById(&a, sid); err != nil { + if err := dbClient.GetAddressableById(&a, sid); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found", http.StatusNotFound) } else { @@ -372,7 +373,7 @@ func restGetServiceByAddressableId(w http.ResponseWriter, r *http.Request) { return } - if err := db.getDeviceServicesByAddressableId(&res, sid); err != nil { + if err := dbClient.GetDeviceServicesByAddressableId(&res, sid); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -394,7 +395,7 @@ func restGetServiceWithLabel(w http.ResponseWriter, r *http.Request) { ls = append(ls, l) res := make([]models.DeviceService, 0) - if err := db.getDeviceServicesWithLabel(&res, ls); err != nil { + if err := dbClient.GetDeviceServicesWithLabel(&res, ls); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -414,7 +415,7 @@ func restGetServiceByName(w http.ResponseWriter, r *http.Request) { } var res models.DeviceService - err = db.getDeviceServiceByName(&res, dn) + err = dbClient.GetDeviceServiceByName(&res, dn) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -435,7 +436,7 @@ func restDeleteServiceById(w http.ResponseWriter, r *http.Request) { // Check if the device service exists and get it var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, id); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -464,7 +465,7 @@ func restDeleteServiceByName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, n); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -490,7 +491,7 @@ func restDeleteServiceByName(w http.ResponseWriter, r *http.Request) { func deleteDeviceService(ds models.DeviceService, w http.ResponseWriter) error { // Delete the associated devices var devices []models.Device - if err := db.getDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { + if err := dbClient.GetDevicesByServiceId(&devices, ds.Service.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -502,7 +503,7 @@ func deleteDeviceService(ds models.DeviceService, w http.ResponseWriter) error { // Delete the associated provision watchers var watchers []models.ProvisionWatcher - if err := db.getProvisionWatchersByServiceId(&watchers, ds.Service.Id.Hex()); err != nil { + if err := dbClient.GetProvisionWatchersByServiceId(&watchers, ds.Service.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -513,7 +514,7 @@ func deleteDeviceService(ds models.DeviceService, w http.ResponseWriter) error { } // Delete the device service - if err := db.deleteDeviceService(ds); err != nil { + if err := dbClient.DeleteDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -534,7 +535,7 @@ func restUpdateServiceLastConnectedById(w http.ResponseWriter, r *http.Request) // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceById(&ds, id); err != nil { + if err = dbClient.GetDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -571,7 +572,7 @@ func restUpdateServiceLastConnectedByName(w http.ResponseWriter, r *http.Request // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, n); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -595,7 +596,7 @@ func restUpdateServiceLastConnectedByName(w http.ResponseWriter, r *http.Request func updateServiceLastConnected(ds models.DeviceService, lc int64, w http.ResponseWriter) error { ds.LastConnected = lc - if err := db.updateDeviceService(ds); err != nil { + if err := dbClient.UpdateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -608,7 +609,7 @@ func restGetServiceById(w http.ResponseWriter, r *http.Request) { var did string = vars[ID] var res models.DeviceService - if err := db.getDeviceServiceById(&res, did); err != nil { + if err := dbClient.GetDeviceServiceById(&res, did); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -638,7 +639,7 @@ func restUpdateServiceOpStateById(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, id); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -678,7 +679,7 @@ func restUpdateServiceOpStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, n); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) } else { @@ -700,7 +701,7 @@ func restUpdateServiceOpStateByName(w http.ResponseWriter, r *http.Request) { // Update the OpState for the device service func updateServiceOpState(ds models.DeviceService, os models.OperatingState, w http.ResponseWriter) error { ds.OperatingState = os - if err := db.updateDeviceService(ds); err != nil { + if err := dbClient.UpdateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -724,7 +725,7 @@ func restUpdateServiceAdminStateById(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, id); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -765,7 +766,7 @@ func restUpdateServiceAdminStateByName(w http.ResponseWriter, r *http.Request) { // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, n); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -788,7 +789,7 @@ func restUpdateServiceAdminStateByName(w http.ResponseWriter, r *http.Request) { // Update the admin state for the device service func updateServiceAdminState(ds models.DeviceService, as models.AdminState, w http.ResponseWriter) error { ds.AdminState = as - if err := db.updateDeviceService(ds); err != nil { + if err := dbClient.UpdateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -809,7 +810,7 @@ func restUpdateServiceLastReportedById(w http.ResponseWriter, r *http.Request) { // Check if the devicde service exists var ds models.DeviceService - if err = db.getDeviceServiceById(&ds, id); err != nil { + if err = dbClient.GetDeviceServiceById(&ds, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -846,7 +847,7 @@ func restUpdateServiceLastReportedByName(w http.ResponseWriter, r *http.Request) // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, n); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) } else { @@ -868,7 +869,7 @@ func restUpdateServiceLastReportedByName(w http.ResponseWriter, r *http.Request) // Update the last reported value for the device service func updateServiceLastReported(ds models.DeviceService, lr int64, w http.ResponseWriter) error { ds.LastReported = lr - if err := db.updateDeviceService(ds); err != nil { + if err := dbClient.UpdateDeviceService(ds); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } diff --git a/core/metadata/rest_provisionwatcher.go b/core/metadata/rest_provisionwatcher.go index 9ef1e93541..a1b0970cc6 100644 --- a/core/metadata/rest_provisionwatcher.go +++ b/core/metadata/rest_provisionwatcher.go @@ -19,6 +19,7 @@ import ( "net/http" "net/url" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" @@ -26,7 +27,7 @@ import ( func restGetProvisionWatchers(w http.ResponseWriter, _ *http.Request) { res := make([]models.ProvisionWatcher, 0) - if err := db.getAllProvisionWatchers(&res); err != nil { + if err := dbClient.GetAllProvisionWatchers(&res); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error(err.Error(), "") return @@ -50,7 +51,7 @@ func restDeleteProvisionWatcherById(w http.ResponseWriter, r *http.Request) { // Check if the provision watcher exists var pw models.ProvisionWatcher - if err := db.getProvisionWatcherById(&pw, id); err != nil { + if err := dbClient.GetProvisionWatcherById(&pw, id); err != nil { errMessage := "Provision Watcher not found by ID: " + err.Error() loggingClient.Error(errMessage, "") http.Error(w, errMessage, http.StatusNotFound) @@ -76,7 +77,7 @@ func restDeleteProvisionWatcherByName(w http.ResponseWriter, r *http.Request) { // Check if the provision watcher exists var pw models.ProvisionWatcher - if err = db.getProvisionWatcherByName(&pw, n); err != nil { + if err = dbClient.GetProvisionWatcherByName(&pw, n); err != nil { if err == mgo.ErrNotFound { errMessage := "Provision watcher not found: " + err.Error() http.Error(w, errMessage, http.StatusNotFound) @@ -99,7 +100,7 @@ func restDeleteProvisionWatcherByName(w http.ResponseWriter, r *http.Request) { // Delete the provision watcher func deleteProvisionWatcher(pw models.ProvisionWatcher, w http.ResponseWriter) error { - if err := db.deleteProvisionWatcher(pw); err != nil { + if err := dbClient.DeleteProvisionWatcher(pw); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -116,7 +117,7 @@ func restGetProvisionWatcherById(w http.ResponseWriter, r *http.Request) { var id string = vars[ID] var res models.ProvisionWatcher - if err := db.getProvisionWatcherById(&res, id); err != nil { + if err := dbClient.GetProvisionWatcherById(&res, id); err != nil { if err == mgo.ErrNotFound { errMessage := "Problem getting provision watcher by ID: " + err.Error() loggingClient.Error(errMessage, "") @@ -142,7 +143,7 @@ func restGetProvisionWatcherByName(w http.ResponseWriter, r *http.Request) { } var res models.ProvisionWatcher - err = db.getProvisionWatcherByName(&res, n) + err = dbClient.GetProvisionWatcherByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusNotFound) @@ -163,14 +164,14 @@ func restGetProvisionWatchersByProfileId(w http.ResponseWriter, r *http.Request) // Check if the device profile exists var dp models.DeviceProfile - if err := db.getDeviceProfileById(&dp, pid); err != nil { + if err := dbClient.GetDeviceProfileById(&dp, pid); err != nil { loggingClient.Error("Device profile not found: "+err.Error(), "") http.Error(w, err.Error(), http.StatusNotFound) return } res := make([]models.ProvisionWatcher, 0) - err := db.getProvisionWatcherByProfileId(&res, pid) + err := dbClient.GetProvisionWatcherByProfileId(&res, pid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -191,7 +192,7 @@ func restGetProvisionWatchersByProfileName(w http.ResponseWriter, r *http.Reques // Check if the device profile exists var dp models.DeviceProfile - if err = db.getDeviceProfileByName(&dp, pn); err != nil { + if err = dbClient.GetDeviceProfileByName(&dp, pn); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device profile not found", http.StatusNotFound) loggingClient.Error("Device profile not found: "+err.Error(), "") @@ -203,7 +204,7 @@ func restGetProvisionWatchersByProfileName(w http.ResponseWriter, r *http.Reques } res := make([]models.ProvisionWatcher, 0) - err = db.getProvisionWatcherByProfileId(&res, dp.Id.Hex()) + err = dbClient.GetProvisionWatcherByProfileId(&res, dp.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -219,14 +220,14 @@ func restGetProvisionWatchersByServiceId(w http.ResponseWriter, r *http.Request) // Check if the device service exists var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, sid); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, sid); err != nil { http.Error(w, "Device Service not found", http.StatusNotFound) loggingClient.Error("Device service not found: "+err.Error(), "") return } res := make([]models.ProvisionWatcher, 0) - err := db.getProvisionWatchersByServiceId(&res, sid) + err := dbClient.GetProvisionWatchersByServiceId(&res, sid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -247,7 +248,7 @@ func restGetProvisionWatchersByServiceName(w http.ResponseWriter, r *http.Reques // Check if the device service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, sn); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, sn); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found", http.StatusNotFound) loggingClient.Error("Device service not found: "+err.Error(), "") @@ -260,7 +261,7 @@ func restGetProvisionWatchersByServiceName(w http.ResponseWriter, r *http.Reques // Get the provision watchers res := make([]models.ProvisionWatcher, 0) - err = db.getProvisionWatchersByServiceId(&res, ds.Service.Id.Hex()) + err = dbClient.GetProvisionWatchersByServiceId(&res, ds.Service.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -286,7 +287,7 @@ func restGetProvisionWatchersByIdentifier(w http.ResponseWriter, r *http.Request } res := make([]models.ProvisionWatcher, 0) - if err := db.getProvisionWatchersByIdentifier(&res, k, v); err != nil { + if err := dbClient.GetProvisionWatchersByIdentifier(&res, k, v); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watchers: "+err.Error(), "") return @@ -314,9 +315,9 @@ func restAddProvisionWatcher(w http.ResponseWriter, r *http.Request) { // Check if the device profile exists // Try by ID - if err := db.getDeviceProfileById(&pw.Profile, pw.Profile.Id.Hex()); err != nil { + if err := dbClient.GetDeviceProfileById(&pw.Profile, pw.Profile.Id.Hex()); err != nil { // Try by name - if err = db.getDeviceProfileByName(&pw.Profile, pw.Profile.Name); err != nil { + if err = dbClient.GetDeviceProfileByName(&pw.Profile, pw.Profile.Name); err != nil { if err == mgo.ErrNotFound { loggingClient.Error("Device profile not found for provision watcher: "+err.Error(), "") http.Error(w, "Device profile not found for provision watcher", http.StatusConflict) @@ -330,9 +331,9 @@ func restAddProvisionWatcher(w http.ResponseWriter, r *http.Request) { // Check if the device service exists // Try by ID - if err := db.getDeviceServiceById(&pw.Service, pw.Service.Service.Id.Hex()); err != nil { + if err := dbClient.GetDeviceServiceById(&pw.Service, pw.Service.Service.Id.Hex()); err != nil { // Try by name - if err = db.getDeviceServiceByName(&pw.Service, pw.Service.Service.Name); err != nil { + if err = dbClient.GetDeviceServiceByName(&pw.Service, pw.Service.Service.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device service not found for provision watcher", http.StatusConflict) loggingClient.Error("Device service not found for provision watcher: "+err.Error(), "") @@ -344,8 +345,8 @@ func restAddProvisionWatcher(w http.ResponseWriter, r *http.Request) { } } - if err := db.addProvisionWatcher(&pw); err != nil { - if err == ErrDuplicateName { + if err := dbClient.AddProvisionWatcher(&pw); err != nil { + if err == db.ErrNotUnique { loggingClient.Error("Duplicate name for the provision watcher: "+err.Error(), "") http.Error(w, "Duplicate name for the provision watcher", http.StatusConflict) } else { @@ -379,9 +380,9 @@ func restUpdateProvisionWatcher(w http.ResponseWriter, r *http.Request) { // Check if the provision watcher exists var to models.ProvisionWatcher // Try by ID - if err := db.getProvisionWatcherById(&to, from.Id.Hex()); err != nil { + if err := dbClient.GetProvisionWatcherById(&to, from.Id.Hex()); err != nil { // Try by name - if err = db.getProvisionWatcherByName(&to, from.Name); err != nil { + if err = dbClient.GetProvisionWatcherByName(&to, from.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Provision watcher not found", http.StatusNotFound) loggingClient.Error("Provision watcher not found: "+err.Error(), "") @@ -398,7 +399,7 @@ func restUpdateProvisionWatcher(w http.ResponseWriter, r *http.Request) { return } - if err := db.updateProvisionWatcher(to); err != nil { + if err := dbClient.UpdateProvisionWatcher(to); err != nil { loggingClient.Error("Problem updating provision watcher: "+err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return @@ -424,7 +425,7 @@ func updateProvisionWatcherFields(from models.ProvisionWatcher, to *models.Provi if from.Name != "" { // Check that the name is unique var checkPW models.ProvisionWatcher - err := db.getProvisionWatcherByName(&checkPW, from.Name) + err := dbClient.GetProvisionWatcherByName(&checkPW, from.Name) if err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -449,7 +450,7 @@ func updateProvisionWatcherFields(from models.ProvisionWatcher, to *models.Provi func notifyProvisionWatcherAssociates(pw models.ProvisionWatcher, action string) error { // Get the device service for the provision watcher var ds models.DeviceService - if err := db.getDeviceServiceById(&ds, pw.Service.Service.Id.Hex()); err != nil { + if err := dbClient.GetDeviceServiceById(&ds, pw.Service.Service.Id.Hex()); err != nil { return err } diff --git a/core/metadata/rest_scheduleevent.go b/core/metadata/rest_scheduleevent.go index 0c59ce451a..ba9565b3d0 100644 --- a/core/metadata/rest_scheduleevent.go +++ b/core/metadata/rest_scheduleevent.go @@ -21,6 +21,7 @@ import ( "strconv" "time" + "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "github.com/robfig/cron" @@ -47,7 +48,7 @@ func msToTime(ms string) (time.Time, error) { func restGetAllScheduleEvents(w http.ResponseWriter, r *http.Request) { res := make([]models.ScheduleEvent, 0) - err := db.getAllScheduleEvents(&res) + err := dbClient.GetAllScheduleEvents(&res) if err != nil { loggingClient.Error("Problem getting schedule events: "+err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -81,7 +82,7 @@ func restAddScheduleEvent(w http.ResponseWriter, r *http.Request) { return } var s models.Schedule - if err := db.getScheduleByName(&s, se.Schedule); err != nil { + if err := dbClient.GetScheduleByName(&s, se.Schedule); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found for schedule event", http.StatusNotFound) loggingClient.Error("Schedule not found for schedule event: "+err.Error(), "") @@ -95,9 +96,9 @@ func restAddScheduleEvent(w http.ResponseWriter, r *http.Request) { // Check for the addressable // Try by ID var a models.Addressable - if err := db.getAddressableById(&a, se.Addressable.Id.Hex()); err != nil { + if err := dbClient.GetAddressableById(&a, se.Addressable.Id.Hex()); err != nil { // Try by Name - if err = db.getAddressableByName(&a, se.Addressable.Name); err != nil { + if err = dbClient.GetAddressableByName(&a, se.Addressable.Name); err != nil { http.Error(w, "Address not found for schedule event", http.StatusNotFound) loggingClient.Error("Addressable for schedule event not found: "+err.Error(), "") return @@ -133,8 +134,8 @@ func restAddScheduleEvent(w http.ResponseWriter, r *http.Request) { return }*/ - if err := db.addScheduleEvent(&se); err != nil { - if err == ErrDuplicateName { + if err := dbClient.AddScheduleEvent(&se); err != nil { + if err == db.ErrNotUnique { http.Error(w, "Duplicate name for schedule event", http.StatusConflict) loggingClient.Error("Duplicate name for schedule event: "+err.Error(), "") } else { @@ -175,7 +176,7 @@ func restUpdateScheduleEvent(w http.ResponseWriter, r *http.Request) { return } - if err := db.updateScheduleEvent(to); err != nil { + if err := dbClient.UpdateScheduleEvent(to); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem updating schedule event: "+err.Error(), "") return @@ -194,9 +195,9 @@ func restUpdateScheduleEvent(w http.ResponseWriter, r *http.Request) { func getScheduleEventByIdOrName(from models.ScheduleEvent, w http.ResponseWriter) (models.ScheduleEvent, error) { var se models.ScheduleEvent // Try by ID - if err := db.getScheduleEventById(&se, from.Id.Hex()); err != nil { + if err := dbClient.GetScheduleEventById(&se, from.Id.Hex()); err != nil { // Try by Name - if err = db.getScheduleEventByName(&se, from.Name); err != nil { + if err = dbClient.GetScheduleEventByName(&se, from.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule Event not found", http.StatusNotFound) loggingClient.Error(err.Error(), "") @@ -221,9 +222,9 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve if (from.Addressable.String() != models.Addressable{}.String()) { // Check if the new addressable exists // Try by ID - if err := db.getAddressableById(&from.Addressable, from.Addressable.Id.Hex()); err != nil { + if err := dbClient.GetAddressableById(&from.Addressable, from.Addressable.Id.Hex()); err != nil { // Try by name - if err = db.getAddressableByName(&from.Addressable, from.Addressable.Name); err != nil { + if err = dbClient.GetAddressableByName(&from.Addressable, from.Addressable.Name); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found for schedule event", http.StatusNotFound) } else { @@ -240,7 +241,7 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve serviceChanged = true // Verify that the new service exists var checkDS models.DeviceService - if err := db.getDeviceServiceByName(&checkDS, from.Service); err != nil { + if err := dbClient.GetDeviceServiceByName(&checkDS, from.Service); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Device Service not found for schedule event", http.StatusNotFound) } else { @@ -257,7 +258,7 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve if from.Schedule != to.Schedule { // Verify that the new schedule exists var checkS models.Schedule - if err := db.getScheduleByName(&checkS, from.Schedule); err != nil { + if err := dbClient.GetScheduleByName(&checkS, from.Schedule); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found for schedule event", http.StatusNotFound) } else { @@ -273,7 +274,7 @@ func updateScheduleEventFields(from models.ScheduleEvent, to *models.ScheduleEve if from.Name != to.Name { // Verify data integrity var reports []models.DeviceReport - if err := db.getDeviceReportsByScheduleEventName(&reports, to.Name); err != nil { + if err := dbClient.GetDeviceReportsByScheduleEventName(&reports, to.Name); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -320,7 +321,7 @@ func restGetScheduleEventByName(w http.ResponseWriter, r *http.Request) { } var res models.ScheduleEvent - err = db.getScheduleEventByName(&res, n) + err = dbClient.GetScheduleEventByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule event not found", http.StatusNotFound) @@ -342,7 +343,7 @@ func restDeleteScheduleEventById(w http.ResponseWriter, r *http.Request) { // Check if the schedule event exists var se models.ScheduleEvent - err := db.getScheduleEventById(&se, id) + err := dbClient.GetScheduleEventById(&se, id) if err != nil { http.Error(w, "Schedule event not found", http.StatusNotFound) loggingClient.Error("Schedule event not found: "+err.Error(), "") @@ -370,7 +371,7 @@ func restDeleteScheduleEventByName(w http.ResponseWriter, r *http.Request) { // Check if the schedule event exists var se models.ScheduleEvent - if err := db.getScheduleEventByName(&se, n); err != nil { + if err := dbClient.GetScheduleEventByName(&se, n); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule event not found", http.StatusNotFound) loggingClient.Error("Schedule event not found: "+err.Error(), "") @@ -396,7 +397,7 @@ func restDeleteScheduleEventByName(w http.ResponseWriter, r *http.Request) { func deleteScheduleEvent(se models.ScheduleEvent, w http.ResponseWriter) error { // Check if the schedule event is still in use by device reports var dr []models.DeviceReport - if err := db.getDeviceReportsByScheduleEventName(&dr, se.Name); err != nil { + if err := dbClient.GetDeviceReportsByScheduleEventName(&dr, se.Name); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -406,7 +407,7 @@ func deleteScheduleEvent(se models.ScheduleEvent, w http.ResponseWriter) error { return err } - if err := db.deleteScheduleEvent(se); err != nil { + if err := dbClient.DeleteScheduleEvent(se); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -423,7 +424,7 @@ func restGetScheduleEventById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var did string = vars[ID] var res models.ScheduleEvent - err := db.getScheduleEventById(&res, did) + err := dbClient.GetScheduleEventById(&res, did) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule event not found", http.StatusNotFound) @@ -447,7 +448,7 @@ func restGetScheduleEventByAddressableId(w http.ResponseWriter, r *http.Request) // Check if the addressable exists var a models.Addressable - if err := db.getAddressableById(&a, aid); err != nil { + if err := dbClient.GetAddressableById(&a, aid); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Addressable not found for schedule event", http.StatusNotFound) loggingClient.Error("Addressable not found for schedule event: "+err.Error(), "") @@ -459,7 +460,7 @@ func restGetScheduleEventByAddressableId(w http.ResponseWriter, r *http.Request) } // Get the schedule events - if err := db.getScheduleEventsByAddressableId(&res, aid); err != nil { + if err := dbClient.GetScheduleEventsByAddressableId(&res, aid); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting schedule events: "+err.Error(), "") return @@ -483,7 +484,7 @@ func restGetScheduleEventByAddressableName(w http.ResponseWriter, r *http.Reques // Check if the addressable exists var a models.Addressable - if err = db.getAddressableByName(&a, an); err != nil { + if err = dbClient.GetAddressableByName(&a, an); err != nil { if err == mgo.ErrNotFound { loggingClient.Error("Addressable not found for schedule event: "+err.Error(), "") http.Error(w, "Addressable not found for schedule event", http.StatusNotFound) @@ -495,7 +496,7 @@ func restGetScheduleEventByAddressableName(w http.ResponseWriter, r *http.Reques } // Get the schedule events - if err = db.getScheduleEventsByAddressableId(&res, a.Id.Hex()); err != nil { + if err = dbClient.GetScheduleEventsByAddressableId(&res, a.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting schedule events: "+err.Error(), "") return @@ -519,7 +520,7 @@ func restGetScheduleEventsByServiceName(w http.ResponseWriter, r *http.Request) // Check if the service exists var ds models.DeviceService - if err = db.getDeviceServiceByName(&ds, sn); err != nil { + if err = dbClient.GetDeviceServiceByName(&ds, sn); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Service not found for schedule event", http.StatusNotFound) loggingClient.Error("Device service not found for schedule event: "+err.Error(), "") @@ -531,7 +532,7 @@ func restGetScheduleEventsByServiceName(w http.ResponseWriter, r *http.Request) } // Get the schedule events - if err = db.getScheduleEventsByServiceName(&res, sn); err != nil { + if err = dbClient.GetScheduleEventsByServiceName(&res, sn); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting schedule events: "+err.Error(), "") return @@ -543,7 +544,7 @@ func restGetScheduleEventsByServiceName(w http.ResponseWriter, r *http.Request) func restGetAllSchedules(w http.ResponseWriter, _ *http.Request) { res := make([]models.Schedule, 0) - err := db.getAllSchedules(&res) + err := dbClient.GetAllSchedules(&res) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) @@ -575,7 +576,7 @@ func restAddSchedule(w http.ResponseWriter, r *http.Request) { // Check if the name is unique var checkS models.Schedule - if err := db.getScheduleByName(&checkS, s.Name); err != nil { + if err := dbClient.GetScheduleByName(&checkS, s.Name); err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Schedule not found: "+err.Error(), "") @@ -612,7 +613,7 @@ func restAddSchedule(w http.ResponseWriter, r *http.Request) { } } - if err := db.addSchedule(&s); err != nil { + if err := dbClient.AddSchedule(&s); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem adding schedule: "+err.Error(), "") return @@ -642,9 +643,9 @@ func restUpdateSchedule(w http.ResponseWriter, r *http.Request) { // Check if the schedule exists var to models.Schedule // Try by ID - if err := db.getScheduleById(&to, from.Id.Hex()); err != nil { + if err := dbClient.GetScheduleById(&to, from.Id.Hex()); err != nil { // Try by name - if err = db.getScheduleByName(&to, from.Name); err != nil { + if err = dbClient.GetScheduleByName(&to, from.Name); err != nil { loggingClient.Error("Schedule not found: "+err.Error(), "") http.Error(w, "Schedule not found", http.StatusNotFound) return @@ -656,7 +657,7 @@ func restUpdateSchedule(w http.ResponseWriter, r *http.Request) { return } - if err := db.updateSchedule(to); err != nil { + if err := dbClient.UpdateSchedule(to); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem updating schedule: "+err.Error(), "") return @@ -709,7 +710,7 @@ func updateScheduleFields(from models.Schedule, to *models.Schedule, w http.Resp if from.Name != "" && from.Name != to.Name { // Check if new name is unique var checkS models.Schedule - if err := db.getScheduleByName(&checkS, from.Name); err != nil { + if err := dbClient.GetScheduleByName(&checkS, from.Name); err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) } @@ -744,7 +745,7 @@ func restGetScheduleById(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var sid string = vars[ID] var res models.Schedule - err := db.getScheduleById(&res, sid) + err := dbClient.GetScheduleById(&res, sid) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found", http.StatusNotFound) @@ -770,7 +771,7 @@ func restGetScheduleByName(w http.ResponseWriter, r *http.Request) { } var res models.Schedule - err = db.getScheduleByName(&res, n) + err = dbClient.GetScheduleByName(&res, n) if err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found", http.StatusNotFound) @@ -792,7 +793,7 @@ func restDeleteScheduleById(w http.ResponseWriter, r *http.Request) { // Check if the schedule exists var s models.Schedule - if err := db.getScheduleById(&s, id); err != nil { + if err := dbClient.GetScheduleById(&s, id); err != nil { if err == mgo.ErrNotFound { http.Error(w, "Schedule not found", http.StatusNotFound) loggingClient.Error("Schedule not found: "+err.Error(), "") @@ -823,7 +824,7 @@ func restDeleteScheduleByName(w http.ResponseWriter, r *http.Request) { // Check if the schedule exists var s models.Schedule - if err = db.getScheduleByName(&s, n); err != nil { + if err = dbClient.GetScheduleByName(&s, n); err != nil { if err == mgo.ErrNotFound { loggingClient.Error("Schedule not found: "+err.Error(), "") http.Error(w, "Schedule not found", http.StatusNotFound) @@ -857,7 +858,7 @@ func deleteSchedule(s models.Schedule, w http.ResponseWriter) error { return err } - if err := db.deleteSchedule(s); err != nil { + if err := dbClient.DeleteSchedule(s); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -873,7 +874,7 @@ func deleteSchedule(s models.Schedule, w http.ResponseWriter) error { // Determine if the scheule is still in use by schedule events func isScheduleStillInUse(s models.Schedule) (bool, error) { var scheduleEvents []models.ScheduleEvent - if err := db.getScheduleEventsByScheduleName(&scheduleEvents, s.Name); err != nil { + if err := dbClient.GetScheduleEventsByScheduleName(&scheduleEvents, s.Name); err != nil { return false, err } if len(scheduleEvents) > 0 { @@ -887,7 +888,7 @@ func isScheduleStillInUse(s models.Schedule) (bool, error) { func notifyScheduleAssociates(s models.Schedule, action string) error { // Get the associated schedule events var events []models.ScheduleEvent - if err := db.getScheduleEventsByScheduleName(&events, s.Name); err != nil { + if err := dbClient.GetScheduleEventsByScheduleName(&events, s.Name); err != nil { return err } @@ -895,7 +896,7 @@ func notifyScheduleAssociates(s models.Schedule, action string) error { var services []models.DeviceService for _, se := range events { var ds models.DeviceService - if err := db.getDeviceServiceByName(&ds, se.Service); err != nil { + if err := dbClient.GetDeviceServiceByName(&ds, se.Service); err != nil { return err } services = append(services, ds) @@ -913,7 +914,7 @@ func notifyScheduleAssociates(s models.Schedule, action string) error { func notifyScheduleEventAssociates(se models.ScheduleEvent, action string) error { // Get the associated device service var ds models.DeviceService - if err := db.getDeviceServiceByName(&ds, se.Service); err != nil { + if err := dbClient.GetDeviceServiceByName(&ds, se.Service); err != nil { return err } From 5152d8f30b9a343ffc44fd2d85200eea9c7c9b32 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Wed, 13 Jun 2018 12:42:37 +0200 Subject: [PATCH 05/10] Adding new metadata memory db Also adding tests for metadata db backends (mongo and memory at the moment) Signed-off-by: Federico Claramonte --- core/db/memory/memory-database.go | 12 + core/db/memory/memory-database_test.go | 7 + core/db/memory/memory-metadata.go | 1107 +++++++++++++++++ core/db/mongo/mongo-client.go | 4 +- core/db/mongo/mongo-client_test.go | 43 + core/db/mongo/mongoOps.go | 87 +- core/db/test/db.go | 26 +- core/db/test/db_metadata.go | 1469 +++++++++++++++++++++++ core/metadata/const.go | 4 +- core/metadata/init.go | 14 + core/metadata/{ => interfaces}/dbOps.go | 31 +- core/metadata/rest_addressable.go | 7 +- core/metadata/rest_device.go | 5 +- core/metadata/rest_deviceprofile.go | 6 +- core/metadata/rest_deviceservice.go | 6 +- core/metadata/rest_provisionwatcher.go | 4 +- 16 files changed, 2716 insertions(+), 116 deletions(-) create mode 100644 core/db/memory/memory-metadata.go create mode 100644 core/db/test/db_metadata.go rename core/metadata/{ => interfaces}/dbOps.go (87%) diff --git a/core/db/memory/memory-database.go b/core/db/memory/memory-database.go index 2eb4de4fb1..39ed165602 100644 --- a/core/db/memory/memory-database.go +++ b/core/db/memory/memory-database.go @@ -22,9 +22,21 @@ import ( ) type MemDB struct { + // Data readings []models.Reading events []models.Event vDescriptors []models.ValueDescriptor + + // Metadata + addressables []models.Addressable + commands []models.Command + deviceServices []models.DeviceService + schedules []models.Schedule + scheduleEvents []models.ScheduleEvent + provisionWatchers []models.ProvisionWatcher + deviceReports []models.DeviceReport + deviceProfiles []models.DeviceProfile + devices []models.Device } func (m *MemDB) CloseSession() { diff --git a/core/db/memory/memory-database_test.go b/core/db/memory/memory-database_test.go index 8f255aabed..881d313ca1 100644 --- a/core/db/memory/memory-database_test.go +++ b/core/db/memory/memory-database_test.go @@ -15,4 +15,11 @@ import ( func TestMemoryDB(t *testing.T) { memory := &MemDB{} test.TestDataDB(t, memory) + test.TestMetadataDB(t, memory) +} + +func BenchmarkMemoryDB(b *testing.B) { + memory := &MemDB{} + + test.BenchmarkDB(b, memory) } diff --git a/core/db/memory/memory-metadata.go b/core/db/memory/memory-metadata.go new file mode 100644 index 0000000000..5735622bea --- /dev/null +++ b/core/db/memory/memory-metadata.go @@ -0,0 +1,1107 @@ +/******************************************************************************* + * Copyright 2018 Cavium + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ + +package memory + +import ( + "errors" + "fmt" + "time" + + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/domain/models" + "gopkg.in/mgo.v2/bson" +) + +// Schedule event +func (m *MemDB) GetAllScheduleEvents(se *[]models.ScheduleEvent) error { + cpy := make([]models.ScheduleEvent, len(m.scheduleEvents)) + copy(cpy, m.scheduleEvents) + *se = cpy + return nil +} + +func (m *MemDB) AddScheduleEvent(se *models.ScheduleEvent) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + se.Created = currentTime + se.Modified = currentTime + se.Id = bson.NewObjectId() + + for _, s := range m.scheduleEvents { + if s.Name == se.Name { + return db.ErrNotUnique + } + } + + validAddressable := false + // Test addressable id or name exists + for _, a := range m.addressables { + if a.Name == se.Addressable.Name { + validAddressable = true + break + } + if a.Id == se.Addressable.Id { + validAddressable = true + break + } + } + + if !validAddressable { + return errors.New("Invalid addressable") + } + + m.scheduleEvents = append(m.scheduleEvents, *se) + return nil +} + +func (m *MemDB) GetScheduleEventByName(se *models.ScheduleEvent, n string) error { + for _, s := range m.scheduleEvents { + if s.Name == n { + err := m.GetAddressableById(&s.Addressable, s.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + se.Addressable.Id.Hex(), se.Id.Hex()) + } + *se = s + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) UpdateScheduleEvent(se models.ScheduleEvent) error { + for i, s := range m.scheduleEvents { + if s.Id == se.Id { + m.scheduleEvents[i] = se + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetScheduleEventById(se *models.ScheduleEvent, id string) error { + for _, s := range m.scheduleEvents { + if s.Id.Hex() == id { + err := m.GetAddressableById(&s.Addressable, s.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + se.Addressable.Id.Hex(), se.Id.Hex()) + } + *se = s + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetScheduleEventsByScheduleName(ses *[]models.ScheduleEvent, n string) error { + l := []models.ScheduleEvent{} + for _, se := range m.scheduleEvents { + if se.Schedule == n { + err := m.GetAddressableById(&se.Addressable, se.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for se %s", + se.Addressable.Id.Hex(), se.Id.Hex()) + } + l = append(l, se) + } + } + *ses = l + return nil +} + +func (m *MemDB) GetScheduleEventsByAddressableId(ses *[]models.ScheduleEvent, id string) error { + l := []models.ScheduleEvent{} + for _, se := range m.scheduleEvents { + if se.Addressable.Id.Hex() == id { + err := m.GetAddressableById(&se.Addressable, se.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for se %s", + se.Addressable.Id.Hex(), se.Id.Hex()) + } + l = append(l, se) + } + } + *ses = l + return nil +} + +func (m *MemDB) GetScheduleEventsByServiceName(ses *[]models.ScheduleEvent, n string) error { + l := []models.ScheduleEvent{} + for _, se := range m.scheduleEvents { + if se.Service == n { + err := m.GetAddressableById(&se.Addressable, se.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for se %s", + se.Addressable.Id.Hex(), se.Id.Hex()) + } + l = append(l, se) + } + } + *ses = l + return nil +} + +func (m *MemDB) DeleteScheduleEvent(se models.ScheduleEvent) error { + for i, s := range m.scheduleEvents { + if s.Id == se.Id { + m.scheduleEvents = append(m.scheduleEvents[:i], m.scheduleEvents[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +// Schedule +func (m *MemDB) GetAllSchedules(s *[]models.Schedule) error { + cpy := make([]models.Schedule, len(m.schedules)) + copy(cpy, m.schedules) + *s = cpy + return nil +} + +func (m *MemDB) AddSchedule(s *models.Schedule) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + s.Created = currentTime + s.Modified = currentTime + s.Id = bson.NewObjectId() + + for _, ss := range m.schedules { + if ss.Name == s.Name { + return db.ErrNotUnique + } + } + + m.schedules = append(m.schedules, *s) + return nil +} + +func (m *MemDB) GetScheduleByName(s *models.Schedule, n string) error { + for _, ss := range m.schedules { + if ss.Name == n { + *s = ss + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) UpdateSchedule(s models.Schedule) error { + s.Modified = time.Now().UnixNano() / int64(time.Millisecond) + for i, ss := range m.schedules { + if ss.Id == s.Id { + m.schedules[i] = s + return nil + } + } + + return db.ErrNotFound +} + +func (m *MemDB) GetScheduleById(s *models.Schedule, id string) error { + for _, ss := range m.schedules { + if ss.Id.Hex() == id { + *s = ss + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) DeleteSchedule(s models.Schedule) error { + for i, ss := range m.schedules { + if ss.Id.Hex() == s.Id.Hex() { + m.schedules = append(m.schedules[:i], m.schedules[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +// Device Report +func (m *MemDB) GetAllDeviceReports(drs *[]models.DeviceReport) error { + cpy := make([]models.DeviceReport, len(m.deviceReports)) + copy(cpy, m.deviceReports) + *drs = cpy + return nil +} + +func (m *MemDB) GetDeviceReportByDeviceName(drs *[]models.DeviceReport, n string) error { + l := []models.DeviceReport{} + for _, dr := range m.deviceReports { + if dr.Name == n { + l = append(l, dr) + } + } + *drs = l + return nil +} + +func (m *MemDB) GetDeviceReportByName(dr *models.DeviceReport, n string) error { + for _, d := range m.deviceReports { + if d.Name == n { + *dr = d + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceReportById(dr *models.DeviceReport, id string) error { + for _, d := range m.deviceReports { + if d.Id.Hex() == id { + *dr = d + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) AddDeviceReport(dr *models.DeviceReport) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + dr.Created = currentTime + dr.Modified = currentTime + dr.Id = bson.NewObjectId() + + dummy := models.DeviceReport{} + if m.GetDeviceReportByName(&dummy, dr.Name) == nil { + return db.ErrNotUnique + } + + m.deviceReports = append(m.deviceReports, *dr) + return nil + +} + +func (m *MemDB) UpdateDeviceReport(dr *models.DeviceReport) error { + for i, d := range m.deviceReports { + if d.Id == dr.Id { + m.deviceReports[i] = *dr + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceReportsByScheduleEventName(drs *[]models.DeviceReport, n string) error { + l := []models.DeviceReport{} + for _, dr := range m.deviceReports { + if dr.Event == n { + l = append(l, dr) + } + } + *drs = l + return nil +} + +func (m *MemDB) DeleteDeviceReport(dr models.DeviceReport) error { + for i, c := range m.deviceReports { + if c.Id == dr.Id { + m.deviceReports = append(m.deviceReports[:i], m.deviceReports[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +// Device +func (m *MemDB) updateDeviceValues(d *models.Device) error { + err := m.GetAddressableById(&d.Addressable, d.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + d.Addressable.Id.Hex(), d.Id.Hex()) + } + err = m.GetDeviceServiceById(&d.Service, d.Service.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find DeviceService %s for ds %s", + d.Service.Id.Hex(), d.Id.Hex()) + } + err = m.GetDeviceProfileById(&d.Profile, d.Profile.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find DeviceProfile %s for ds %s", + d.Profile.Id.Hex(), d.Id.Hex()) + } + return nil +} + +type deviceCmp func(models.Device) bool + +func (m *MemDB) getDeviceBy(d *models.Device, f deviceCmp) error { + for _, dd := range m.devices { + if f(dd) { + if err := m.updateDeviceValues(&dd); err != nil { + return err + } + *d = dd + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) getDevicesBy(d *[]models.Device, f deviceCmp) error { + l := []models.Device{} + for _, dd := range m.devices { + if f(dd) { + if err := m.updateDeviceValues(&dd); err != nil { + return err + } + l = append(l, dd) + } + } + *d = l + return nil +} + +func (m *MemDB) UpdateDevice(d models.Device) error { + for i, dd := range m.devices { + if dd.Id == d.Id { + m.devices[i] = d + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceById(d *models.Device, id string) error { + return m.getDeviceBy(d, + func(dd models.Device) bool { + return dd.Id.Hex() == id + }) +} + +func (m *MemDB) GetDeviceByName(d *models.Device, n string) error { + return m.getDeviceBy(d, + func(dd models.Device) bool { + return dd.Name == n + }) +} + +func (m *MemDB) GetAllDevices(d *[]models.Device) error { + cpy := make([]models.Device, len(m.devices)) + copy(cpy, m.devices) + *d = cpy + return nil +} + +func (m *MemDB) GetDevicesByProfileId(d *[]models.Device, id string) error { + return m.getDevicesBy(d, + func(dd models.Device) bool { + return dd.Profile.Id.Hex() == id + }) +} + +func (m *MemDB) GetDevicesByServiceId(d *[]models.Device, id string) error { + return m.getDevicesBy(d, + func(dd models.Device) bool { + return dd.Service.Id.Hex() == id + }) +} + +func (m *MemDB) GetDevicesByAddressableId(d *[]models.Device, id string) error { + return m.getDevicesBy(d, + func(dd models.Device) bool { + return dd.Addressable.Id.Hex() == id + }) +} + +func (m *MemDB) GetDevicesWithLabel(d *[]models.Device, l string) error { + return m.getDevicesBy(d, + func(dd models.Device) bool { + return stringInSlice(l, dd.Labels) + }) +} + +func (m *MemDB) AddDevice(d *models.Device) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + d.Created = currentTime + d.Modified = currentTime + d.Id = bson.NewObjectId() + + for _, dd := range m.devices { + if dd.Name == d.Name { + return db.ErrNotUnique + } + } + + validAddressable := false + // Test addressable id or name exists + for _, a := range m.addressables { + if a.Name == d.Addressable.Name { + validAddressable = true + break + } + if a.Id == d.Addressable.Id { + validAddressable = true + break + } + } + + if !validAddressable { + return errors.New("Invalid addressable") + } + + m.devices = append(m.devices, *d) + return nil +} + +func (m *MemDB) DeleteDevice(d models.Device) error { + for i, dd := range m.devices { + if dd.Id.Hex() == d.Id.Hex() { + m.devices = append(m.devices[:i], m.devices[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) UpdateDeviceProfile(dp *models.DeviceProfile) error { + for i, d := range m.deviceProfiles { + if d.Id == dp.Id { + m.deviceProfiles[i] = *dp + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) AddDeviceProfile(d *models.DeviceProfile) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + d.Created = currentTime + d.Modified = currentTime + d.Id = bson.NewObjectId() + + for _, dd := range m.deviceProfiles { + if dd.Name == d.Name { + return db.ErrNotUnique + } + } + + m.deviceProfiles = append(m.deviceProfiles, *d) + return nil +} + +func (m *MemDB) GetAllDeviceProfiles(d *[]models.DeviceProfile) error { + cpy := make([]models.DeviceProfile, len(m.deviceProfiles)) + copy(cpy, m.deviceProfiles) + *d = cpy + return nil +} + +func (m *MemDB) GetDeviceProfileById(d *models.DeviceProfile, id string) error { + for _, dp := range m.deviceProfiles { + if dp.Id.Hex() == id { + *d = dp + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) DeleteDeviceProfile(dp models.DeviceProfile) error { + for i, d := range m.deviceProfiles { + if d.Id == dp.Id { + m.deviceProfiles = append(m.deviceProfiles[:i], m.deviceProfiles[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceProfilesByModel(dps *[]models.DeviceProfile, model string) error { + l := []models.DeviceProfile{} + for _, dp := range m.deviceProfiles { + if dp.Model == model { + l = append(l, dp) + } + } + *dps = l + return nil +} + +func (m *MemDB) GetDeviceProfilesWithLabel(dps *[]models.DeviceProfile, label string) error { + l := []models.DeviceProfile{} + for _, dp := range m.deviceProfiles { + if stringInSlice(label, dp.Labels) { + l = append(l, dp) + } + } + *dps = l + return nil +} + +func (m *MemDB) GetDeviceProfilesByManufacturerModel(dps *[]models.DeviceProfile, man string, mod string) error { + l := []models.DeviceProfile{} + for _, dp := range m.deviceProfiles { + if dp.Manufacturer == man && dp.Model == mod { + l = append(l, dp) + } + } + *dps = l + return nil +} + +func (m *MemDB) GetDeviceProfilesByManufacturer(dps *[]models.DeviceProfile, man string) error { + l := []models.DeviceProfile{} + for _, dp := range m.deviceProfiles { + if dp.Manufacturer == man { + l = append(l, dp) + } + } + *dps = l + return nil +} + +func (m *MemDB) GetDeviceProfileByName(d *models.DeviceProfile, n string) error { + for _, dp := range m.deviceProfiles { + if dp.Name == n { + *d = dp + return nil + } + } + return db.ErrNotFound +} + +// Addressable +func (m *MemDB) UpdateAddressable(updated *models.Addressable, orig *models.Addressable) error { + if updated == nil { + return nil + } + if updated.Name != "" { + orig.Name = updated.Name + } + if updated.Protocol != "" { + orig.Protocol = updated.Protocol + } + if updated.Address != "" { + orig.Address = updated.Address + } + if updated.Port != int(0) { + orig.Port = updated.Port + } + if updated.Path != "" { + orig.Path = updated.Path + } + if updated.Publisher != "" { + orig.Publisher = updated.Publisher + } + if updated.User != "" { + orig.User = updated.User + } + if updated.Password != "" { + orig.Password = updated.Password + } + if updated.Topic != "" { + orig.Topic = updated.Topic + } + + for i, aa := range m.addressables { + if aa.Id == orig.Id { + m.addressables[i] = *orig + return nil + } + } + + return db.ErrNotFound +} + +func (m *MemDB) AddAddressable(a *models.Addressable) (bson.ObjectId, error) { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + a.Created = currentTime + a.Modified = currentTime + a.Id = bson.NewObjectId() + + for _, aa := range m.addressables { + if aa.Name == a.Name { + return a.Id, db.ErrNotUnique + } + } + + m.addressables = append(m.addressables, *a) + return a.Id, nil +} + +type addressableCmp func(models.Addressable) bool + +func (m *MemDB) getAddressableBy(a *models.Addressable, f addressableCmp) error { + for _, aa := range m.addressables { + if f(aa) { + *a = aa + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) getAddressablesBy(a *[]models.Addressable, f addressableCmp) { + l := []models.Addressable{} + for _, aa := range m.addressables { + if f(aa) { + l = append(l, aa) + } + } + *a = l +} + +func (m *MemDB) GetAddressableById(a *models.Addressable, id string) error { + return m.getAddressableBy(a, + func(aa models.Addressable) bool { + return aa.Id.Hex() == id + }) +} + +func (m *MemDB) GetAddressableByName(a *models.Addressable, n string) error { + return m.getAddressableBy(a, + func(aa models.Addressable) bool { + return aa.Name == n + }) +} + +func (m *MemDB) GetAddressablesByTopic(a *[]models.Addressable, t string) error { + m.getAddressablesBy(a, + func(aa models.Addressable) bool { + return aa.Topic == t + }) + return nil +} + +func (m *MemDB) GetAddressablesByPort(a *[]models.Addressable, p int) error { + m.getAddressablesBy(a, + func(aa models.Addressable) bool { + return aa.Port == p + }) + return nil +} + +func (m *MemDB) GetAddressablesByPublisher(a *[]models.Addressable, p string) error { + m.getAddressablesBy(a, + func(aa models.Addressable) bool { + return aa.Publisher == p + }) + return nil +} + +func (m *MemDB) GetAddressablesByAddress(a *[]models.Addressable, add string) error { + m.getAddressablesBy(a, + func(aa models.Addressable) bool { + return aa.Address == add + }) + return nil +} + +func (m *MemDB) GetAddressables(d *[]models.Addressable) error { + cpy := make([]models.Addressable, len(m.addressables)) + copy(cpy, m.addressables) + *d = cpy + return nil +} + +func (m *MemDB) DeleteAddressable(a models.Addressable) error { + for i, aa := range m.addressables { + if aa.Id.Hex() == a.Id.Hex() { + m.addressables = append(m.addressables[:i], m.addressables[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +// Device service +func (m *MemDB) UpdateDeviceService(ds models.DeviceService) error { + for i, d := range m.deviceServices { + if d.Id == ds.Id { + m.deviceServices[i] = ds + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error { + l := []models.DeviceService{} + for _, ds := range m.deviceServices { + if ds.Addressable.Id.Hex() == id { + err := m.GetAddressableById(&ds.Addressable, ds.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + ds.Addressable.Id.Hex(), ds.Id.Hex()) + } + l = append(l, ds) + } + } + *d = l + return nil +} + +func (m *MemDB) GetDeviceServicesWithLabel(d *[]models.DeviceService, label string) error { + l := []models.DeviceService{} + for _, ds := range m.deviceServices { + if stringInSlice(label, ds.Labels) { + err := m.GetAddressableById(&ds.Addressable, ds.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + ds.Addressable.Id.Hex(), ds.Id.Hex()) + } + l = append(l, ds) + } + } + *d = l + return nil +} + +func (m *MemDB) GetDeviceServiceById(d *models.DeviceService, id string) error { + for _, ds := range m.deviceServices { + if ds.Id.Hex() == id { + err := m.GetAddressableById(&ds.Addressable, ds.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + ds.Addressable.Id.Hex(), ds.Id.Hex()) + } + *d = ds + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceServiceByName(d *models.DeviceService, n string) error { + for _, ds := range m.deviceServices { + if ds.Name == n { + err := m.GetAddressableById(&ds.Addressable, ds.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + ds.Addressable.Id.Hex(), ds.Id.Hex()) + } + *d = ds + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetAllDeviceServices(d *[]models.DeviceService) error { + for _, ds := range m.deviceServices { + err := m.GetAddressableById(&ds.Addressable, ds.Addressable.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find addressable %s for ds %s", + ds.Addressable.Id.Hex(), ds.Id.Hex()) + } + } + cpy := make([]models.DeviceService, len(m.deviceServices)) + copy(cpy, m.deviceServices) + *d = cpy + return nil +} + +func (m *MemDB) AddDeviceService(ds *models.DeviceService) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + ds.Created = currentTime + ds.Modified = currentTime + ds.Id = bson.NewObjectId() + + for _, d := range m.deviceServices { + if d.Name == ds.Name { + return db.ErrNotUnique + } + } + + validAddressable := false + // Test addressable id or name exists + for _, a := range m.addressables { + if a.Name == ds.Addressable.Name { + validAddressable = true + break + } + if a.Id == ds.Addressable.Id { + validAddressable = true + break + } + } + + if !validAddressable { + return errors.New("Invalid addressable") + } + + m.deviceServices = append(m.deviceServices, *ds) + return nil +} + +func (m *MemDB) DeleteDeviceService(ds models.DeviceService) error { + for i, d := range m.deviceServices { + if d.Id == ds.Id { + m.deviceServices = append(m.deviceServices[:i], m.deviceServices[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +// Provision watcher +type provisionWatcherComp func(models.ProvisionWatcher) bool + +func (m *MemDB) getProvisionWatcherBy(pw *models.ProvisionWatcher, f provisionWatcherComp) error { + for _, p := range m.provisionWatchers { + if f(p) { + err := m.GetDeviceServiceById(&p.Service, p.Service.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find DeviceService %s for ds %s", + p.Service.Id.Hex(), p.Id.Hex()) + } + err = m.GetDeviceProfileById(&p.Profile, p.Profile.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find DeviceProfile %s for ds %s", + p.Profile.Id.Hex(), p.Id.Hex()) + } + *pw = p + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) getProvisionWatchersBy(pws *[]models.ProvisionWatcher, f provisionWatcherComp) error { + l := []models.ProvisionWatcher{} + for _, pw := range m.provisionWatchers { + if f(pw) { + err := m.GetDeviceServiceById(&pw.Service, pw.Service.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find DeviceService %s for ds %s", + pw.Service.Id.Hex(), pw.Id.Hex()) + } + err = m.GetDeviceProfileById(&pw.Profile, pw.Profile.Id.Hex()) + if err != nil { + return fmt.Errorf("Could not find DeviceProfile %s for ds %s", + pw.Profile.Id.Hex(), pw.Id.Hex()) + } + l = append(l, pw) + } + } + *pws = l + return nil +} + +func (m *MemDB) GetProvisionWatcherById(pw *models.ProvisionWatcher, id string) error { + return m.getProvisionWatcherBy(pw, + func(p models.ProvisionWatcher) bool { + return p.Id.Hex() == id + }) +} + +func (m *MemDB) GetAllProvisionWatchers(pw *[]models.ProvisionWatcher) error { + *pw = m.provisionWatchers + return nil +} + +func (m *MemDB) GetProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error { + return m.getProvisionWatcherBy(pw, + func(p models.ProvisionWatcher) bool { + return p.Name == n + }) +} + +func (m *MemDB) GetProvisionWatchersByProfileId(pw *[]models.ProvisionWatcher, id string) error { + return m.getProvisionWatchersBy(pw, + func(p models.ProvisionWatcher) bool { + return p.Profile.Id.Hex() == id + }) +} + +func (m *MemDB) GetProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error { + return m.getProvisionWatchersBy(pw, + func(p models.ProvisionWatcher) bool { + return p.Service.Id.Hex() == id + }) +} + +func (m *MemDB) GetProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error { + return m.getProvisionWatchersBy(pw, + func(p models.ProvisionWatcher) bool { + return p.Identifiers[k] == v + }) +} + +func (m *MemDB) updateProvisionWatcherValues(pw *models.ProvisionWatcher) error { + // get Device Service + validDeviceService := false + var dev models.DeviceService + var err error + if pw.Service.Id.Hex() != "" { + if err = m.GetDeviceServiceById(&dev, pw.Service.Id.Hex()); err == nil { + validDeviceService = true + } + } else if pw.Service.Name != "" { + if err = m.GetDeviceServiceByName(&dev, pw.Service.Name); err == nil { + validDeviceService = true + } + } else { + return errors.New("Device Service ID or Name is required") + } + if !validDeviceService { + return fmt.Errorf("Invalid DeviceService: %v", err) + } + pw.Service = dev + + // get Device Profile + validDeviceProfile := false + var dp models.DeviceProfile + if pw.Profile.Id.Hex() != "" { + if err = m.GetDeviceProfileById(&dp, pw.Profile.Id.Hex()); err == nil { + validDeviceProfile = true + } + } else if pw.Profile.Name != "" { + if err = m.GetDeviceProfileByName(&dp, pw.Profile.Name); err == nil { + validDeviceProfile = true + } + } else { + return errors.New("Device Profile ID or Name is required") + } + if !validDeviceProfile { + return fmt.Errorf("Invalid DeviceProfile: %v", err) + } + pw.Profile = dp + return nil +} + +func (m *MemDB) AddProvisionWatcher(pw *models.ProvisionWatcher) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + pw.Created = currentTime + pw.Modified = currentTime + pw.Id = bson.NewObjectId() + + p := models.ProvisionWatcher{} + if err := m.GetProvisionWatcherByName(&p, pw.Name); err == nil { + return db.ErrNotUnique + } + + if err := m.updateProvisionWatcherValues(pw); err != nil { + return err + } + m.provisionWatchers = append(m.provisionWatchers, *pw) + return nil +} + +func (m *MemDB) UpdateProvisionWatcher(pw models.ProvisionWatcher) error { + pw.Modified = time.Now().UnixNano() / int64(time.Millisecond) + + if err := m.updateProvisionWatcherValues(&pw); err != nil { + return err + } + for i, p := range m.provisionWatchers { + if pw.Id == p.Id { + m.provisionWatchers[i] = p + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) DeleteProvisionWatcher(pw models.ProvisionWatcher) error { + for i, p := range m.provisionWatchers { + if p.Id.Hex() == pw.Id.Hex() { + m.provisionWatchers = append(m.provisionWatchers[:i], m.provisionWatchers[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +// Command +func (m *MemDB) GetCommandById(c *models.Command, id string) error { + for _, cc := range m.commands { + if cc.Id.Hex() == id { + *c = cc + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetCommandByName(d *[]models.Command, name string) error { + cmds := []models.Command{} + for _, cc := range m.commands { + if cc.Name == name { + cmds = append(cmds, cc) + } + } + *d = cmds + return nil +} + +func (m *MemDB) AddCommand(c *models.Command) error { + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + c.Created = currentTime + c.Modified = currentTime + c.Id = bson.NewObjectId() + + m.commands = append(m.commands, *c) + return nil +} + +func (m *MemDB) GetAllCommands(d *[]models.Command) error { + cpy := make([]models.Command, len(m.commands)) + copy(cpy, m.commands) + *d = cpy + return nil +} + +func (m *MemDB) UpdateCommand(updated *models.Command, orig *models.Command) error { + if updated == nil { + return nil + } + if updated.Name != "" { + orig.Name = updated.Name + } + if updated.Get != nil && (updated.Get.String() != models.Get{}.String()) { + orig.Get = updated.Get + } + if updated.Put != nil && (updated.Put.String() != models.Put{}.String()) { + orig.Put = updated.Put + } + if updated.Origin != 0 { + orig.Origin = updated.Origin + } + + for i, c := range m.commands { + if c.Id == orig.Id { + m.commands[i] = *orig + return nil + } + } + + return db.ErrNotFound +} + +func (m *MemDB) DeleteCommandById(id string) error { + for i, c := range m.commands { + if c.Id.Hex() == id { + m.commands = append(m.commands[:i], m.commands[i+1:]...) + return nil + } + } + return db.ErrNotFound +} + +func (m *MemDB) GetDeviceProfilesUsingCommand(dps *[]models.DeviceProfile, c models.Command) error { + l := []models.DeviceProfile{} + for _, dp := range m.deviceProfiles { + for _, cc := range dp.Commands { + if cc.Id == c.Id { + l = append(l, dp) + break + } + } + } + *dps = l + return nil +} diff --git a/core/db/mongo/mongo-client.go b/core/db/mongo/mongo-client.go index ff567cf923..1b45952910 100644 --- a/core/db/mongo/mongo-client.go +++ b/core/db/mongo/mongo-client.go @@ -92,7 +92,7 @@ func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { e.Readings[i].Device = e.Device ui = append(ui, e.Readings[i]) } - err := s.DB(mc.Database.Name).C(db.ReadingsCollection).Insert(ui...) + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(ui...) if err != nil { return e.ID, err } @@ -102,7 +102,7 @@ func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { me := MongoEvent{Event: *e} // Add the event - err := s.DB(mc.Database.Name).C(db.EventsCollection).Insert(me) + err := s.DB(mc.database.Name).C(db.EventsCollection).Insert(me) if err != nil { return e.ID, err } diff --git a/core/db/mongo/mongo-client_test.go b/core/db/mongo/mongo-client_test.go index eaef5f96d3..84549a2085 100644 --- a/core/db/mongo/mongo-client_test.go +++ b/core/db/mongo/mongo-client_test.go @@ -32,6 +32,49 @@ func TestMongoDB(t *testing.T) { mongo := NewClient(config) test.TestDataDB(t, mongo) + + config.DatabaseName = "metadata" + mongo = NewClient(config) + + err := mongo.Connect() + if err != nil { + t.Fatalf("Could not connect with mongodb: %v", err) + } + + s := mongo.getSessionCopy() + defer s.Close() + + _, err = s.DB(mongo.database.Name).C(db.Addressable).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + + _, err = s.DB(mongo.database.Name).C(db.DeviceService).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + _, err = s.DB(mongo.database.Name).C(db.DeviceProfile).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + _, err = s.DB(mongo.database.Name).C(db.DeviceReport).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + _, err = s.DB(mongo.database.Name).C(db.ScheduleEvent).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + _, err = s.DB(mongo.database.Name).C(db.Device).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + _, err = s.DB(mongo.database.Name).C(db.ProvisionWatcher).RemoveAll(nil) + if err != nil { + t.Fatalf("Error removing previous data: %v", err) + } + + test.TestMetadataDB(t, mongo) } func BenchmarkMongoDB(b *testing.B) { diff --git a/core/db/mongo/mongoOps.go b/core/db/mongo/mongoOps.go index 9bada3fbd7..07ea1fb06b 100644 --- a/core/db/mongo/mongoOps.go +++ b/core/db/mongo/mongoOps.go @@ -157,6 +157,7 @@ func (m *MongoClient) GetScheduleEvents(se *[]models.ScheduleEvent, q bson.M) er return err } + *se = []models.ScheduleEvent{} for _, mse := range mses { *se = append(*se, mse.ScheduleEvent) } @@ -194,15 +195,14 @@ func (m *MongoClient) AddSchedule(sch *models.Schedule) error { if err != nil { return err } else if count > 0 { - err := errors.New("Schedule already exist") - return err + return db.ErrNotUnique } ts := makeTimestamp() sch.Created = ts sch.Modified = ts sch.Id = bson.NewObjectId() - return col.Insert(s) + return col.Insert(sch) } func (m *MongoClient) UpdateSchedule(sch models.Schedule) error { @@ -382,11 +382,6 @@ func (m *MongoClient) GetDevicesByServiceId(d *[]models.Device, sid string) erro func (m *MongoClient) GetDevicesByAddressableId(d *[]models.Device, aid string) error { if bson.IsObjectIdHex(aid) { - // Check if the addressable exists - var a *models.Addressable - if m.GetAddressableById(a, aid) == mgo.ErrNotFound { - return mgo.ErrNotFound - } return m.GetDevices(d, bson.M{"addressable.$id": bson.ObjectIdHex(aid)}) } else { err := errors.New("mgoGetDevicesByAddressableId Invalid Object ID " + aid) @@ -394,8 +389,10 @@ func (m *MongoClient) GetDevicesByAddressableId(d *[]models.Device, aid string) } } -func (m *MongoClient) GetDevicesWithLabel(d *[]models.Device, l []string) error { - return m.GetDevices(d, bson.M{"labels": bson.M{"$in": l}}) +func (m *MongoClient) GetDevicesWithLabel(d *[]models.Device, l string) error { + var ls []string + ls = append(ls, l) + return m.GetDevices(d, bson.M{"labels": bson.M{"$in": ls}}) } func (m *MongoClient) GetDevices(d *[]models.Device, q bson.M) error { @@ -409,6 +406,7 @@ func (m *MongoClient) GetDevices(d *[]models.Device, q bson.M) error { return err } + *d = []models.Device{} for _, md := range mds { *d = append(*d, md.Device) } @@ -450,8 +448,10 @@ func (m *MongoClient) GetDeviceProfilesByModel(dp *[]models.DeviceProfile, model return m.GetDeviceProfiles(dp, bson.M{"model": model}) } -func (m *MongoClient) GetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error { - return m.GetDeviceProfiles(dp, bson.M{"labels": bson.M{"$in": l}}) +func (m *MongoClient) GetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l string) error { + var ls []string + ls = append(ls, l) + return m.GetDeviceProfiles(dp, bson.M{"labels": bson.M{"$in": ls}}) } func (m *MongoClient) GetDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error { return m.GetDeviceProfiles(dp, bson.M{"manufacturer": man, "model": mod}) @@ -476,6 +476,7 @@ func (m *MongoClient) GetDeviceProfiles(d *[]models.DeviceProfile, q bson.M) err return err } + *d = []models.DeviceProfile{} for _, mdp := range mdps { *d = append(*d, mdp.DeviceProfile) } @@ -614,7 +615,7 @@ func (m *MongoClient) GetAddressableById(a *models.Addressable, id string) error } } -func (m *MongoClient) AddAddressable(a *models.Addressable) error { +func (m *MongoClient) AddAddressable(a *models.Addressable) (bson.ObjectId, error) { s := m.session.Copy() defer s.Close() col := s.DB(m.database.Name).C(db.Addressable) @@ -622,20 +623,16 @@ func (m *MongoClient) AddAddressable(a *models.Addressable) error { // check if the name exist count, err := col.Find(bson.M{"name": a.Name}).Count() if err != nil { - return err + return a.Id, err } else if count > 0 { - return db.ErrNotUnique + return a.Id, db.ErrNotUnique } ts := makeTimestamp() a.Created = ts a.Id = bson.NewObjectId() err = col.Insert(a) - if err != nil { - return err - } - - return nil + return a.Id, err } func (m *MongoClient) GetAddressableByName(a *models.Addressable, n string) error { @@ -701,8 +698,10 @@ func (m *MongoClient) GetDeviceServicesByAddressableId(d *[]models.DeviceService } } -func (m *MongoClient) GetDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error { - return m.GetDeviceServices(d, bson.M{"labels": bson.M{"$in": l}}) +func (m *MongoClient) GetDeviceServicesWithLabel(d *[]models.DeviceService, l string) error { + var ls []string + ls = append(ls, l) + return m.GetDeviceServices(d, bson.M{"labels": bson.M{"$in": ls}}) } func (m *MongoClient) GetDeviceServices(d *[]models.DeviceService, q bson.M) error { @@ -714,10 +713,10 @@ func (m *MongoClient) GetDeviceServices(d *[]models.DeviceService, q bson.M) err if err != nil { return err } + *d = []models.DeviceService{} for _, mds := range mdss { *d = append(*d, mds.DeviceService) } - return nil } @@ -738,20 +737,13 @@ func (m *MongoClient) GetDeviceService(d *models.DeviceService, q bson.M) error func (m *MongoClient) AddDeviceService(d *models.DeviceService) error { s := m.session.Copy() defer s.Close() - col := s.DB(m.database.Name).C(db.DeviceService) - // check if the name exist - count, err := col.Find(bson.M{"name": d.Service.Name}).Count() - if err != nil { - return err - } else if count > 0 { - return db.ErrNotUnique - } + col := s.DB(m.database.Name).C(db.DeviceService) ts := makeTimestamp() - d.Service.Created = ts - d.Service.Modified = ts - d.Service.Id = bson.NewObjectId() + d.Created = ts + d.Modified = ts + d.Id = bson.NewObjectId() // MongoDeviceService handles the DBRefs mds := MongoDeviceService{DeviceService: *d} @@ -763,12 +755,12 @@ func (m *MongoClient) UpdateDeviceService(deviceService models.DeviceService) er defer s.Close() c := s.DB(m.database.Name).C(db.DeviceService) - deviceService.Service.Modified = makeTimestamp() + deviceService.Modified = makeTimestamp() // Handle DBRefs mds := MongoDeviceService{DeviceService: deviceService} - return c.UpdateId(deviceService.Service.Id, mds) + return c.UpdateId(deviceService.Id, mds) } func (m *MongoClient) DeleteDeviceService(ds models.DeviceService) error { @@ -796,7 +788,7 @@ func (m *MongoClient) GetProvisionWatchersByServiceId(pw *[]models.ProvisionWatc } } -func (m *MongoClient) GetProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error { +func (m *MongoClient) GetProvisionWatchersByProfileId(pw *[]models.ProvisionWatcher, id string) error { if bson.IsObjectIdHex(id) { return m.GetProvisionWatchers(pw, bson.M{"profile.$id": bson.ObjectIdHex(id)}) } else { @@ -845,6 +837,7 @@ func (m *MongoClient) GetProvisionWatchers(pw *[]models.ProvisionWatcher, q bson return err } + *pw = []models.ProvisionWatcher{} for _, mpw := range mpws { *pw = append(*pw, mpw.ProvisionWatcher) } @@ -865,10 +858,10 @@ func (m *MongoClient) AddProvisionWatcher(pw *models.ProvisionWatcher) error { // get Device Service var dev models.DeviceService - if pw.Service.Service.Id.Hex() != "" { - m.GetDeviceServiceById(&dev, pw.Service.Service.Id.Hex()) - } else if pw.Service.Service.Name != "" { - m.GetDeviceServiceByName(&dev, pw.Service.Service.Name) + if pw.Service.Id.Hex() != "" { + m.GetDeviceServiceById(&dev, pw.Service.Id.Hex()) + } else if pw.Service.Name != "" { + m.GetDeviceServiceByName(&dev, pw.Service.Name) } else { return errors.New("Device Service ID or Name is required") } @@ -1011,15 +1004,3 @@ func (m *MongoClient) DeleteCommandById(id string) error { return col.RemoveId(bson.ObjectIdHex(id)) } - -func (m *MongoClient) DeleteByName(c string, n string) error { - s := m.session.Copy() - defer s.Close() - col := s.DB(m.database.Name).C(c) - err := col.Remove(bson.M{"name": n}) - if err != nil { - return err - } - - return nil -} diff --git a/core/db/test/db.go b/core/db/test/db.go index ac42f0133c..8868e0314c 100644 --- a/core/db/test/db.go +++ b/core/db/test/db.go @@ -63,7 +63,6 @@ func populateDbEvents(db clients.DBClient, count int, pushed int64) (bson.Object e.Pushed = pushed var err error id, err = db.AddEvent(&e) - fmt.Printf("%s -> %v\n", name, err) if err != nil { return id, err } @@ -226,7 +225,7 @@ func testDBReadings(t *testing.T, db clients.DBClient) { if len(readings) != 110 { t.Fatalf("There should be 110 readings, not %d", len(readings)) } - readings, err = db.ReadingsByCreationTime(beforeTime, beforeTime+10, 100) + readings, err = db.ReadingsByCreationTime(beforeTime, beforeTime+30, 100) if err != nil { t.Fatalf("Error getting ReadingsByCreationTime: %v", err) } @@ -636,31 +635,14 @@ func TestDataDB(t *testing.T, db clients.DBClient) { db.CloseSession() } -func TestMemoryDB(t *testing.T) { - memory := &memDB{} - testDB(t, memory) -} - -func BenchmarkMemoryDB(b *testing.B) { - config := DBConfiguration{ - DbType: MEMORY, - } - - benchmarkDB(b, config) -} - -func benchmarkDB(b *testing.B, config DBConfiguration) { - db, err := NewDBClient(config) - if err != nil { - b.Fatalf("Could not connect with database: %v", err) - } +func BenchmarkDB(b *testing.B, db clients.DBClient) { benchmarkReadings(b, db) benchmarkEvents(b, db) db.CloseSession() } -func benchmarkReadings(b *testing.B, db DBClient) { +func benchmarkReadings(b *testing.B, db clients.DBClient) { // Remove previous events and readings db.ScrubAllEvents() @@ -724,7 +706,7 @@ func benchmarkReadings(b *testing.B, db DBClient) { }) } -func benchmarkEvents(b *testing.B, db DBClient) { +func benchmarkEvents(b *testing.B, db clients.DBClient) { // Remove previous events and readings db.ScrubAllEvents() diff --git a/core/db/test/db_metadata.go b/core/db/test/db_metadata.go new file mode 100644 index 0000000000..a272f09c8a --- /dev/null +++ b/core/db/test/db_metadata.go @@ -0,0 +1,1469 @@ +// +// Copyright (c) 2018 Cavium +// +// SPDX-License-Identifier: Apache-2.0 +// + +package test + +import ( + "fmt" + "testing" + + "github.com/edgexfoundry/edgex-go/core/domain/models" + "github.com/edgexfoundry/edgex-go/core/metadata/interfaces" + "gopkg.in/mgo.v2/bson" +) + +func TestMetadataDB(t *testing.T, db interfaces.DBClient) { + + testDBAddressables(t, db) + testDBCommand(t, db) + testDBDeviceService(t, db) + testDBSchedule(t, db) + testDBDeviceReport(t, db) + testDBScheduleEvent(t, db) + testDBDeviceProfile(t, db) + testDBDevice(t, db) + testDBProvisionWatcher(t, db) + + db.CloseSession() + // Calling CloseSession twice to test that there is no panic when closing an + // already closed db + db.CloseSession() +} + +func getAddressable(i int, prefix string) models.Addressable { + name := fmt.Sprintf("%sname%d", prefix, i) + a := models.Addressable{} + a.Name = name + a.Protocol = name + a.HTTPMethod = name + a.Address = name + a.Port = i + a.Path = name + a.Publisher = name + a.User = name + a.Password = name + a.Topic = name + return a +} + +func getDeviceService(db interfaces.DBClient, i int) (models.DeviceService, error) { + name := fmt.Sprintf("name%d", i) + ds := models.DeviceService{} + ds.Name = name + ds.AdminState = "ENABLED" + ds.Addressable = getAddressable(i, "ds_") + ds.Labels = append(ds.Labels, name) + ds.OperatingState = "ENABLED" + ds.LastConnected = 5 + ds.LastReported = 5 + ds.Description = name + var err error + _, err = db.AddAddressable(&ds.Addressable) + if err != nil { + return ds, fmt.Errorf("Error creating addressable: %v", err) + } + return ds, nil +} + +func getCommand(db interfaces.DBClient, i int) models.Command { + name := fmt.Sprintf("name%d", i) + c := models.Command{} + c.Name = name + c.Put = &models.Put{} + c.Get = &models.Get{} + return c +} + +func getDeviceProfile(db interfaces.DBClient, i int) (models.DeviceProfile, error) { + name := fmt.Sprintf("name%d", i) + dp := models.DeviceProfile{} + dp.Name = name + dp.Manufacturer = name + dp.Model = name + dp.Labels = append(dp.Labels, name) + dp.Objects = dp.Labels + // TODO + // dp.DeviceResources = append(dp.DeviceResources, name) + // dp.Resources = append(dp.Resources, name) + c := getCommand(db, i) + err := db.AddCommand(&c) + if err != nil { + return dp, err + } + dp.Commands = append(dp.Commands, c) + return dp, nil +} + +func populateAddressable(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + var err error + a := getAddressable(i, "") + id, err = db.AddAddressable(&a) + if err != nil { + return id, err + } + } + return id, nil +} + +func populateCommand(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + c := getCommand(db, i) + err := db.AddCommand(&c) + if err != nil { + return id, err + } + id = c.Id + } + return id, nil +} + +func populateDeviceService(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + + for i := 0; i < count; i++ { + ds, err := getDeviceService(db, i) + if err != nil { + return id, nil + } + err = db.AddDeviceService(&ds) + id = ds.Id + if err != nil { + return id, fmt.Errorf("Error creating device service: %v", err) + } + } + return id, nil +} + +func populateSchedule(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + var err error + name := fmt.Sprintf("name%d", i) + s := models.Schedule{} + s.Name = name + s.Start = name + s.End = name + s.Frequency = name + s.Cron = name + s.RunOnce = false + err = db.AddSchedule(&s) + if err != nil { + return id, err + } + id = s.Id + } + return id, nil +} + +func populateDeviceReport(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + var err error + name := fmt.Sprintf("name%d", i) + dr := models.DeviceReport{} + dr.Name = name + dr.Device = name + dr.Event = name + dr.Expected = append(dr.Expected, name) + err = db.AddDeviceReport(&dr) + if err != nil { + return id, err + } + id = dr.Id + } + return id, nil +} + +func populateScheduleEvent(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + var err error + name := fmt.Sprintf("name%d", i) + se := models.ScheduleEvent{} + se.Name = name + se.Schedule = name + se.Parameters = name + se.Service = name + se.Addressable = getAddressable(i, "se_") + _, err = db.AddAddressable(&se.Addressable) + if err != nil { + return id, fmt.Errorf("Error creating addressable: %v", err) + } + err = db.AddScheduleEvent(&se) + if err != nil { + return id, err + } + id = se.Id + } + return id, nil +} + +func populateDevice(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + var err error + name := fmt.Sprintf("name%d", i) + d := models.Device{} + d.Name = name + d.AdminState = "ENABLED" + d.OperatingState = "ENABLED" + d.LastConnected = 4 + d.LastReported = 4 + d.Labels = append(d.Labels, name) + + d.Addressable = getAddressable(i, "device") + _, err = db.AddAddressable(&d.Addressable) + if err != nil { + return id, fmt.Errorf("Error creating addressable: %v", err) + } + + d.Service, err = getDeviceService(db, i) + if err != nil { + return id, nil + } + err = db.AddDeviceService(&d.Service) + if err != nil { + return id, fmt.Errorf("Error creating DeviceService: %v", err) + } + d.Profile, err = getDeviceProfile(db, i) + if err != nil { + return id, fmt.Errorf("Error getting DeviceProfile: %v", err) + } + err = db.AddDeviceProfile(&d.Profile) + if err != nil { + return id, fmt.Errorf("Error creating DeviceProfile: %v", err) + } + err = db.AddDevice(&d) + if err != nil { + return id, err + } + id = d.Id + } + return id, nil +} + +func populateDeviceProfile(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + dp, err := getDeviceProfile(db, i) + if err != nil { + return id, fmt.Errorf("Error getting DeviceProfile: %v", err) + } + err = db.AddDeviceProfile(&dp) + if err != nil { + return id, err + } + id = dp.Id + } + return id, nil +} + +func populateProvisionWatcher(db interfaces.DBClient, count int) (bson.ObjectId, error) { + var id bson.ObjectId + for i := 0; i < count; i++ { + var err error + name := fmt.Sprintf("name%d", i) + d := models.ProvisionWatcher{} + d.Name = name + d.OperatingState = "ENABLED" + d.Identifiers = make(map[string]string) + d.Identifiers["name"] = name + + d.Service, err = getDeviceService(db, i) + if err != nil { + return id, err + } + err = db.AddDeviceService(&d.Service) + if err != nil { + return id, fmt.Errorf("Error creating DeviceService: %v", err) + } + d.Profile, err = getDeviceProfile(db, i) + if err != nil { + return id, fmt.Errorf("Error getting DeviceProfile: %v", err) + } + err = db.AddDeviceProfile(&d.Profile) + if err != nil { + return id, fmt.Errorf("Error creating DeviceProfile: %v", err) + } + err = db.AddProvisionWatcher(&d) + if err != nil { + return id, err + } + id = d.Id + } + return id, nil +} + +func clearAddressables(t *testing.T, db interfaces.DBClient) { + var addrs []models.Addressable + err := db.GetAddressables(&addrs) + if err != nil { + t.Fatalf("Error getting addressables %v", err) + } + for _, a := range addrs { + if err = db.DeleteAddressable(a); err != nil { + t.Fatalf("Error removing addressable %v: %v", a, err) + } + } +} + +func clearDevices(t *testing.T, db interfaces.DBClient) { + var ds []models.Device + err := db.GetAllDevices(&ds) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + for _, d := range ds { + if err = db.DeleteDevice(d); err != nil { + t.Fatalf("Error removing device %v: %v", d, err) + } + } +} + +func clearSchedules(t *testing.T, db interfaces.DBClient) { + var ss []models.Schedule + err := db.GetAllSchedules(&ss) + if err != nil { + t.Fatalf("Error getting schedule %v", err) + } + for _, s := range ss { + if err = db.DeleteSchedule(s); err != nil { + t.Fatalf("Error removing schedule %v: %v", s, err) + } + } +} + +func clearScheduleEvents(t *testing.T, db interfaces.DBClient) { + var ss []models.ScheduleEvent + err := db.GetAllScheduleEvents(&ss) + if err != nil { + t.Fatalf("Error getting schedule %v", err) + } + for _, s := range ss { + if err = db.DeleteScheduleEvent(s); err != nil { + t.Fatalf("Error removing schedule %v: %v", s, err) + } + } +} + +func clearDeviceServices(t *testing.T, db interfaces.DBClient) { + var dss []models.DeviceService + err := db.GetAllDeviceServices(&dss) + if err != nil { + t.Fatalf("Error getting deviceServices %v", err) + } + for _, ds := range dss { + if err = db.DeleteDeviceService(ds); err != nil { + t.Fatalf("Error removing deviceService %v: %v", ds, err) + } + } +} + +func clearDeviceReports(t *testing.T, db interfaces.DBClient) { + var drs []models.DeviceReport + err := db.GetAllDeviceReports(&drs) + if err != nil { + t.Fatalf("Error getting deviceReports %v", err) + } + for _, ds := range drs { + if err = db.DeleteDeviceReport(ds); err != nil { + t.Fatalf("Error removing deviceReport %v: %v", ds, err) + } + } +} + +func clearDeviceProfiles(t *testing.T, db interfaces.DBClient) { + var dps []models.DeviceProfile + err := db.GetAllDeviceProfiles(&dps) + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + + for _, ds := range dps { + if err = db.DeleteDeviceProfile(ds); err != nil { + t.Fatalf("Error removing deviceProfile %v: %v", ds, err) + } + } +} + +func testDBAddressables(t *testing.T, db interfaces.DBClient) { + var addrs []models.Addressable + + clearAddressables(t, db) + + id, err := populateAddressable(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + // Error to have an Addressable with the same name + _, err = populateAddressable(db, 1) + if err == nil { + t.Fatalf("Should not be able to add a duplicated addressable\n") + } + + err = db.GetAddressables(&addrs) + if err != nil { + t.Fatalf("Error getting addressables %v", err) + } + if len(addrs) != 100 { + t.Fatalf("There should be 100 addressables instead of %d", len(addrs)) + } + a := models.Addressable{} + err = db.GetAddressableById(&a, id.Hex()) + if err != nil { + t.Fatalf("Error getting addressable by id %v", err) + } + if a.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", a.Id, id) + } + err = db.GetAddressableById(&a, "INVALID") + if err == nil { + t.Fatalf("Addressable should not be found") + } + err = db.GetAddressableByName(&a, "name1") + if err != nil { + t.Fatalf("Error getting addressable by name %v", err) + } + if a.Name != "name1" { + t.Fatalf("name does not match %s - %s", a.Name, "name1") + } + err = db.GetAddressableByName(&a, "INVALID") + if err == nil { + t.Fatalf("Addressable should not be found") + } + + err = db.GetAddressablesByTopic(&addrs, "name1") + if err != nil { + t.Fatalf("Error getting addressables by topic: %v", err) + } + if len(addrs) != 1 { + t.Fatalf("There should be 1 addressable, not %d", len(addrs)) + } + + err = db.GetAddressablesByTopic(&addrs, "INVALID") + if err != nil { + t.Fatalf("Error getting addressables by topic: %v", err) + } + if len(addrs) != 0 { + t.Fatalf("There should be no addressables, not %d", len(addrs)) + } + + err = db.GetAddressablesByPort(&addrs, 2) + if err != nil { + t.Fatalf("Error getting addressables by port: %v", err) + } + if len(addrs) != 1 { + t.Fatalf("There should be 1 addressable, not %d", len(addrs)) + } + + err = db.GetAddressablesByPort(&addrs, -1) + if err != nil { + t.Fatalf("Error getting addressables by port: %v", err) + } + if len(addrs) != 0 { + t.Fatalf("There should be no addressables, not %d", len(addrs)) + } + + err = db.GetAddressablesByPublisher(&addrs, "name1") + if err != nil { + t.Fatalf("Error getting addressables by publisher: %v", err) + } + if len(addrs) != 1 { + t.Fatalf("There should be 1 addressable, not %d", len(addrs)) + } + + err = db.GetAddressablesByPublisher(&addrs, "INVALID") + if err != nil { + t.Fatalf("Error getting addressables by publisher: %v", err) + } + if len(addrs) != 0 { + t.Fatalf("There should be no addressables, not %d", len(addrs)) + } + + err = db.GetAddressablesByAddress(&addrs, "name1") + if err != nil { + t.Fatalf("Error getting addressables by Address: %v", err) + } + if len(addrs) != 1 { + t.Fatalf("There should be 1 addressable, not %d", len(addrs)) + } + + err = db.GetAddressablesByAddress(&addrs, "INVALID") + if err != nil { + t.Fatalf("Error getting addressables by Address: %v", err) + } + if len(addrs) != 0 { + t.Fatalf("There should be no addressables, not %d", len(addrs)) + } + + err = db.GetAddressableById(&a, id.Hex()) + if err != nil { + t.Fatalf("Error getting addressable %v", err) + } + err = db.GetAddressableByName(&a, "name1") + if err != nil { + t.Fatalf("Error getting addressable %v", err) + } + + aa := models.Addressable{} + aa.Id = id + aa.Name = "name" + err = db.UpdateAddressable(&aa, &a) + if err != nil { + t.Fatalf("Error updating Addressable %v", err) + } + err = db.GetAddressableByName(&a, "name1") + if err == nil { + t.Fatalf("Addresable name1 should be renamed") + } + err = db.GetAddressableByName(&a, "name") + if err != nil { + t.Fatalf("Addresable name should be renamed") + } + + // aa.Name = "name2" + // err = db.UpdateAddressable(&aa, &a) + // if err == nil { + // t.Fatalf("Error updating Addressable %v", err) + // } + + a.Id = "INVALID" + a.Name = "INVALID" + err = db.DeleteAddressable(a) + if err == nil { + t.Fatalf("Addressable should not be deleted") + } + + err = db.GetAddressableByName(&a, "name") + if err != nil { + t.Fatalf("Error getting addressable") + } + err = db.DeleteAddressable(a) + if err != nil { + t.Fatalf("Addressable should be deleted: %v", err) + } + + clearAddressables(t, db) +} + +func testDBCommand(t *testing.T, db interfaces.DBClient) { + var commands []models.Command + err := db.GetAllCommands(&commands) + if err != nil { + t.Fatalf("Error getting commands %v", err) + } + for _, c := range commands { + if err = db.DeleteCommandById(c.Id.Hex()); err != nil { + t.Fatalf("Error removing command %v", err) + } + } + + id, err := populateCommand(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + err = db.GetAllCommands(&commands) + if err != nil { + t.Fatalf("Error getting commands %v", err) + } + if len(commands) != 100 { + t.Fatalf("There should be 100 commands instead of %d", len(commands)) + } + c := models.Command{} + err = db.GetCommandById(&c, id.Hex()) + if err != nil { + t.Fatalf("Error getting command by id %v", err) + } + if c.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", c.Id, id) + } + err = db.GetCommandById(&c, "INVALID") + if err == nil { + t.Fatalf("Command should not be found") + } + + err = db.GetCommandByName(&commands, "name1") + if err != nil { + t.Fatalf("Error getting commands by name %v", err) + } + if len(commands) != 1 { + t.Fatalf("There should be 1 commands instead of %d", len(commands)) + } + + err = db.GetCommandByName(&commands, "INVALID") + if err != nil { + t.Fatalf("Error getting commands by name %v", err) + } + if len(commands) != 0 { + t.Fatalf("There should be 1 commands instead of %d", len(commands)) + } + + cc := models.Command{} + cc.Id = id + cc.Get = &models.Get{} + cc.Put = &models.Put{} + cc.Name = "name" + err = db.UpdateCommand(&cc, &c) + if err != nil { + t.Fatalf("Error updating Command %v", err) + } + + c.Id = "INVALID" + err = db.UpdateCommand(&cc, &c) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteCommandById("INVALID") + if err == nil { + t.Fatalf("Command should not be deleted") + } + + err = db.DeleteCommandById(id.Hex()) + if err != nil { + t.Fatalf("Command should be deleted: %v", err) + } +} + +func testDBDeviceService(t *testing.T, db interfaces.DBClient) { + var deviceServices []models.DeviceService + + clearDeviceServices(t, db) + id, err := populateDeviceService(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + ds2 := models.DeviceService{} + ds2.Name = "name1" + err = db.AddDeviceService(&ds2) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + + err = db.GetAllDeviceServices(&deviceServices) + if err != nil { + t.Fatalf("Error getting deviceServices %v", err) + } + if len(deviceServices) != 100 { + t.Fatalf("There should be 100 deviceServices instead of %d", len(deviceServices)) + } + ds := models.DeviceService{} + err = db.GetDeviceServiceById(&ds, id.Hex()) + if err != nil { + t.Fatalf("Error getting deviceService by id %v", err) + } + if ds.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", ds.Id, id) + } + err = db.GetDeviceServiceById(&ds, "INVALID") + if err == nil { + t.Fatalf("DeviceService should not be found") + } + + err = db.GetDeviceServiceByName(&ds, "name1") + if err != nil { + t.Fatalf("Error getting deviceServices by name %v", err) + } + if ds.Name != "name1" { + t.Fatalf("The ds should be named name1 instead of %s", ds.Name) + } + + err = db.GetDeviceServiceByName(&ds, "INVALID") + if err == nil { + t.Fatalf("There should be a not found error") + } + + err = db.GetDeviceServicesByAddressableId(&deviceServices, ds.Addressable.Id.Hex()) + if err != nil { + t.Fatalf("Error getting deviceServices by addressable id %v", err) + } + if len(deviceServices) != 1 { + t.Fatalf("There should be 1 deviceServices instead of %d", len(deviceServices)) + } + err = db.GetDeviceServicesByAddressableId(&deviceServices, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting deviceServices by addressable id") + } + + err = db.GetDeviceServicesWithLabel(&deviceServices, "name3") + if err != nil { + t.Fatalf("Error getting deviceServices by addressable id %v", err) + } + if len(deviceServices) != 1 { + t.Fatalf("There should be 1 deviceServices instead of %d", len(deviceServices)) + } + err = db.GetDeviceServicesWithLabel(&deviceServices, "INVALID") + if err != nil { + t.Fatalf("Error getting deviceServices by addressable id %v", err) + } + if len(deviceServices) != 0 { + t.Fatalf("There should be 0 deviceServices instead of %d", len(deviceServices)) + } + + ds.Id = id + ds.Name = "name" + err = db.UpdateDeviceService(ds) + if err != nil { + t.Fatalf("Error updating DeviceService %v", err) + } + + ds.Id = "INVALID" + err = db.UpdateDeviceService(ds) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteDeviceService(ds) + if err == nil { + t.Fatalf("DeviceService should not be deleted") + } + + ds.Id = id + err = db.DeleteDeviceService(ds) + if err != nil { + t.Fatalf("DeviceService should be deleted: %v", err) + } + + clearDeviceServices(t, db) +} + +func testDBSchedule(t *testing.T, db interfaces.DBClient) { + var schedules []models.Schedule + + clearSchedules(t, db) + id, err := populateSchedule(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + e := models.Schedule{} + e.Name = "name1" + err = db.AddSchedule(&e) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + + err = db.GetAllSchedules(&schedules) + if err != nil { + t.Fatalf("Error getting schedules %v", err) + } + if len(schedules) != 100 { + t.Fatalf("There should be 100 schedules instead of %d", len(schedules)) + } + + err = db.GetScheduleById(&e, id.Hex()) + if err != nil { + t.Fatalf("Error getting schedule by id %v", err) + } + if e.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", e.Id, id) + } + err = db.GetScheduleById(&e, "INVALID") + if err == nil { + t.Fatalf("Schedule should not be found") + } + + err = db.GetScheduleByName(&e, "name1") + if err != nil { + t.Fatalf("Error getting schedule by id %v", err) + } + if e.Name != "name1" { + t.Fatalf("Id does not match %s - %s", e.Id, id) + } + err = db.GetScheduleByName(&e, "INVALID") + if err == nil { + t.Fatalf("Schedule should not be found") + } + + e2 := models.Schedule{} + e2.Id = id + e2.Name = "name" + err = db.UpdateSchedule(e2) + if err != nil { + t.Fatalf("Error updating Schedule %v", err) + } + + e2.Id = "INVALID" + err = db.UpdateSchedule(e2) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteSchedule(e2) + if err == nil { + t.Fatalf("Schedule should not be deleted") + } + + e2.Id = id + err = db.DeleteSchedule(e2) + if err != nil { + t.Fatalf("Schedule should be deleted: %v", err) + } +} + +func testDBDeviceReport(t *testing.T, db interfaces.DBClient) { + var deviceReports []models.DeviceReport + + clearDeviceReports(t, db) + + id, err := populateDeviceReport(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + e := models.DeviceReport{} + e.Name = "name1" + err = db.AddDeviceReport(&e) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + + err = db.GetAllDeviceReports(&deviceReports) + if err != nil { + t.Fatalf("Error getting deviceReports %v", err) + } + if len(deviceReports) != 100 { + t.Fatalf("There should be 100 deviceReports instead of %d", len(deviceReports)) + } + + err = db.GetDeviceReportById(&e, id.Hex()) + if err != nil { + t.Fatalf("Error getting deviceReport by id %v", err) + } + if e.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", e.Id, id) + } + err = db.GetDeviceReportById(&e, "INVALID") + if err == nil { + t.Fatalf("DeviceReport should not be found") + } + + err = db.GetDeviceReportByName(&e, "name1") + if err != nil { + t.Fatalf("Error getting deviceReport by id %v", err) + } + if e.Name != "name1" { + t.Fatalf("Id does not match %s - %s", e.Id, id) + } + err = db.GetDeviceReportByName(&e, "INVALID") + if err == nil { + t.Fatalf("DeviceReport should not be found") + } + + err = db.GetDeviceReportByDeviceName(&deviceReports, "name1") + if err != nil { + t.Fatalf("Error getting deviceReports %v", err) + } + if len(deviceReports) != 1 { + t.Fatalf("There should be 1 deviceReports instead of %d", len(deviceReports)) + } + + err = db.GetDeviceReportByDeviceName(&deviceReports, "name") + if err != nil { + t.Fatalf("Error getting deviceReports %v", err) + } + if len(deviceReports) != 0 { + t.Fatalf("There should be 0 deviceReports instead of %d", len(deviceReports)) + } + + err = db.GetDeviceReportsByScheduleEventName(&deviceReports, "name1") + if err != nil { + t.Fatalf("Error getting deviceReports %v", err) + } + if len(deviceReports) != 1 { + t.Fatalf("There should be 1 deviceReports instead of %d", len(deviceReports)) + } + + err = db.GetDeviceReportsByScheduleEventName(&deviceReports, "name") + if err != nil { + t.Fatalf("Error getting deviceReports %v", err) + } + if len(deviceReports) != 0 { + t.Fatalf("There should be 0 deviceReports instead of %d", len(deviceReports)) + } + + e2 := models.DeviceReport{} + e2.Id = id + e2.Name = "name" + err = db.UpdateDeviceReport(&e2) + if err != nil { + t.Fatalf("Error updating DeviceReport %v", err) + } + + e2.Id = "INVALID" + err = db.UpdateDeviceReport(&e2) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteDeviceReport(e2) + if err == nil { + t.Fatalf("DeviceReport should not be deleted") + } + + e2.Id = id + err = db.DeleteDeviceReport(e2) + if err != nil { + t.Fatalf("DeviceReport should be deleted: %v", err) + } +} + +func testDBScheduleEvent(t *testing.T, db interfaces.DBClient) { + var scheduleEvents []models.ScheduleEvent + + clearScheduleEvents(t, db) + clearAddressables(t, db) + id, err := populateScheduleEvent(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + e := models.ScheduleEvent{} + e.Name = "name1" + err = db.AddScheduleEvent(&e) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + e.Name = "name_not_used" + e.Addressable.Name = "unused" + err = db.AddScheduleEvent(&e) + if err == nil { + t.Fatalf("Should be an error adding an event with not existing addressable") + } + + err = db.GetAllScheduleEvents(&scheduleEvents) + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 100 { + t.Fatalf("There should be 100 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + err = db.GetScheduleEventById(&e, id.Hex()) + if err != nil { + t.Fatalf("Error getting ScheduleEvent by id %v", err) + } + if e.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", e.Id, id) + } + err = db.GetScheduleEventById(&e, "INVALID") + if err == nil { + t.Fatalf("ScheduleEvent should not be found") + } + + err = db.GetScheduleEventByName(&e, "name1") + if err != nil { + t.Fatalf("Error getting ScheduleEvent by id %v", err) + } + if e.Name != "name1" { + t.Fatalf("Id does not match %s - %s", e.Id, id) + } + err = db.GetScheduleEventByName(&e, "INVALID") + if err == nil { + t.Fatalf("ScheduleEvent should not be found") + } + + err = db.GetScheduleEventsByScheduleName(&scheduleEvents, "name1") + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 1 { + t.Fatalf("There should be 1 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + err = db.GetScheduleEventsByScheduleName(&scheduleEvents, "name") + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 0 { + t.Fatalf("There should be 0 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + err = db.GetScheduleEventsByAddressableId(&scheduleEvents, e.Addressable.Id.Hex()) + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 1 { + t.Fatalf("There should be 1 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + err = db.GetScheduleEventsByAddressableId(&scheduleEvents, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 0 { + t.Fatalf("There should be 0 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + err = db.GetScheduleEventsByServiceName(&scheduleEvents, "name1") + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 1 { + t.Fatalf("There should be 1 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + err = db.GetScheduleEventsByServiceName(&scheduleEvents, "name") + if err != nil { + t.Fatalf("Error getting ScheduleEvents %v", err) + } + if len(scheduleEvents) != 0 { + t.Fatalf("There should be 0 ScheduleEvents instead of %d", len(scheduleEvents)) + } + + e.Id = id + e.Name = "name" + err = db.UpdateScheduleEvent(e) + if err != nil { + t.Fatalf("Error updating ScheduleEvent %v", err) + } + + e.Id = "INVALID" + err = db.UpdateScheduleEvent(e) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteScheduleEvent(e) + if err == nil { + t.Fatalf("ScheduleEvent should not be deleted") + } + + e.Id = id + err = db.DeleteScheduleEvent(e) + if err != nil { + t.Fatalf("ScheduleEvent should be deleted: %v", err) + } +} + +func testDBDeviceProfile(t *testing.T, db interfaces.DBClient) { + var deviceProfiles []models.DeviceProfile + + clearAddressables(t, db) + clearDeviceProfiles(t, db) + id, err := populateDeviceProfile(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + dp := models.DeviceProfile{} + dp.Name = "name1" + err = db.AddDeviceProfile(&dp) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + + err = db.GetAllDeviceProfiles(&deviceProfiles) + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 100 { + t.Fatalf("There should be 100 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfileById(&dp, id.Hex()) + if err != nil { + t.Fatalf("Error getting deviceProfile by id %v", err) + } + if dp.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", dp.Id, id) + } + err = db.GetDeviceProfileById(&dp, "INVALID") + if err == nil { + t.Fatalf("DeviceProfile should not be found") + } + + err = db.GetDeviceProfileByName(&dp, "name1") + if err != nil { + t.Fatalf("Error getting deviceProfile by id %v", err) + } + if dp.Name != "name1" { + t.Fatalf("Id does not match %s - %s", dp.Id, id) + } + err = db.GetDeviceProfileByName(&dp, "INVALID") + if err == nil { + t.Fatalf("DeviceProfile should not be found") + } + + err = db.GetDeviceProfilesByModel(&deviceProfiles, "name1") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 1 { + t.Fatalf("There should be 1 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesByModel(&deviceProfiles, "name") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 0 { + t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesByManufacturer(&deviceProfiles, "name1") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 1 { + t.Fatalf("There should be 1 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesByManufacturer(&deviceProfiles, "name") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 0 { + t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesByManufacturerModel(&deviceProfiles, "name1", "name1") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 1 { + t.Fatalf("There should be 1 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesByManufacturerModel(&deviceProfiles, "name", "name1") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 0 { + t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesWithLabel(&deviceProfiles, "name1") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 1 { + t.Fatalf("There should be 1 deviceProfiles instead of %d", len(deviceProfiles)) + } + + err = db.GetDeviceProfilesWithLabel(&deviceProfiles, "name") + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 0 { + t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles)) + } + + c := models.Command{} + c.Id = dp.Commands[0].Id + + err = db.GetDeviceProfilesUsingCommand(&deviceProfiles, c) + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 1 { + t.Fatalf("There should be 1 deviceProfiles instead of %d", len(deviceProfiles)) + } + + c.Id = bson.NewObjectId() + err = db.GetDeviceProfilesUsingCommand(&deviceProfiles, c) + if err != nil { + t.Fatalf("Error getting deviceProfiles %v", err) + } + if len(deviceProfiles) != 0 { + t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles)) + } + + d2 := models.DeviceProfile{} + d2.Id = id + d2.Name = "name" + err = db.UpdateDeviceProfile(&d2) + if err != nil { + t.Fatalf("Error updating DeviceProfile %v", err) + } + + d2.Id = "INVALID" + err = db.UpdateDeviceProfile(&d2) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteDeviceProfile(d2) + if err == nil { + t.Fatalf("DeviceProfile should not be deleted") + } + + d2.Id = id + err = db.DeleteDeviceProfile(d2) + if err != nil { + t.Fatalf("DeviceProfile should be deleted: %v", err) + } + + clearDeviceProfiles(t, db) +} + +func testDBDevice(t *testing.T, db interfaces.DBClient) { + var devices []models.Device + + clearDeviceProfiles(t, db) + clearDeviceServices(t, db) + clearAddressables(t, db) + clearDevices(t, db) + id, err := populateDevice(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + d := models.Device{} + d.Name = "name1" + err = db.AddDevice(&d) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + + err = db.GetAllDevices(&devices) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 100 { + t.Fatalf("There should be 100 devices instead of %d", len(devices)) + } + + err = db.GetDeviceById(&d, id.Hex()) + if err != nil { + t.Fatalf("Error getting device by id %v", err) + } + if d.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", d.Id, id) + } + err = db.GetDeviceById(&d, "INVALID") + if err == nil { + t.Fatalf("Device should not be found") + } + + err = db.GetDeviceByName(&d, "name1") + if err != nil { + t.Fatalf("Error getting device by id %v", err) + } + if d.Name != "name1" { + t.Fatalf("Id does not match %s - %s", d.Id, id) + } + err = db.GetDeviceByName(&d, "INVALID") + if err == nil { + t.Fatalf("Device should not be found") + } + + err = db.GetDevicesByProfileId(&devices, d.Profile.Id.Hex()) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 1 { + t.Fatalf("There should be 1 devices instead of %d", len(devices)) + } + + err = db.GetDevicesByProfileId(&devices, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 0 { + t.Fatalf("There should be 0 devices instead of %d", len(devices)) + } + + err = db.GetDevicesByServiceId(&devices, d.Service.Id.Hex()) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 1 { + t.Fatalf("There should be 1 devices instead of %d", len(devices)) + } + + err = db.GetDevicesByServiceId(&devices, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 0 { + t.Fatalf("There should be 0 devices instead of %d", len(devices)) + } + + err = db.GetDevicesByAddressableId(&devices, d.Addressable.Id.Hex()) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 1 { + t.Fatalf("There should be 1 devices instead of %d", len(devices)) + } + + err = db.GetDevicesByAddressableId(&devices, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 0 { + t.Fatalf("There should be 0 devices instead of %d", len(devices)) + } + + err = db.GetDevicesWithLabel(&devices, "name1") + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 1 { + t.Fatalf("There should be 1 devices instead of %d", len(devices)) + } + + err = db.GetDevicesWithLabel(&devices, "name") + if err != nil { + t.Fatalf("Error getting devices %v", err) + } + if len(devices) != 0 { + t.Fatalf("There should be 0 devices instead of %d", len(devices)) + } + + d.Id = id + d.Name = "name" + err = db.UpdateDevice(d) + if err != nil { + t.Fatalf("Error updating Device %v", err) + } + + d.Id = "INVALID" + err = db.UpdateDevice(d) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteDevice(d) + if err == nil { + t.Fatalf("Device should not be deleted") + } + + d.Id = id + err = db.DeleteDevice(d) + if err != nil { + t.Fatalf("Device should be deleted: %v", err) + } +} + +func testDBProvisionWatcher(t *testing.T, db interfaces.DBClient) { + var provisionWatchers []models.ProvisionWatcher + + clearDeviceProfiles(t, db) + clearDeviceServices(t, db) + clearAddressables(t, db) + id, err := populateProvisionWatcher(db, 100) + if err != nil { + t.Fatalf("Error populating db: %v\n", err) + } + + pw := models.ProvisionWatcher{} + pw.Name = "name1" + err = db.AddProvisionWatcher(&pw) + if err == nil { + t.Fatalf("Should be an error adding an existing name") + } + + err = db.GetAllProvisionWatchers(&provisionWatchers) + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 100 { + t.Fatalf("There should be 100 provisionWatchers instead of %d", len(provisionWatchers)) + } + + err = db.GetProvisionWatcherById(&pw, id.Hex()) + if err != nil { + t.Fatalf("Error getting provisionWatcher by id %v", err) + } + if pw.Id.Hex() != id.Hex() { + t.Fatalf("Id does not match %s - %s", pw.Id, id) + } + err = db.GetProvisionWatcherById(&pw, "INVALID") + if err == nil { + t.Fatalf("ProvisionWatcher should not be found") + } + + err = db.GetProvisionWatcherByName(&pw, "name1") + if err != nil { + t.Fatalf("Error getting provisionWatcher by id %v", err) + } + if pw.Name != "name1" { + t.Fatalf("Id does not match %s - %s", pw.Id, id) + } + err = db.GetProvisionWatcherByName(&pw, "INVALID") + if err == nil { + t.Fatalf("ProvisionWatcher should not be found") + } + + err = db.GetProvisionWatchersByServiceId(&provisionWatchers, pw.Service.Id.Hex()) + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 1 { + t.Fatalf("There should be 1 provisionWatchers instead of %d", len(provisionWatchers)) + } + + err = db.GetProvisionWatchersByServiceId(&provisionWatchers, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 0 { + t.Fatalf("There should be 0 provisionWatchers instead of %d", len(provisionWatchers)) + } + + err = db.GetProvisionWatchersByProfileId(&provisionWatchers, pw.Profile.Id.Hex()) + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 1 { + t.Fatalf("There should be 1 provisionWatchers instead of %d", len(provisionWatchers)) + } + + err = db.GetProvisionWatchersByProfileId(&provisionWatchers, bson.NewObjectId().Hex()) + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 0 { + t.Fatalf("There should be 0 provisionWatchers instead of %d", len(provisionWatchers)) + } + + err = db.GetProvisionWatchersByIdentifier(&provisionWatchers, "name", "name1") + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 1 { + t.Fatalf("There should be 1 provisionWatchers instead of %d", len(provisionWatchers)) + } + + err = db.GetProvisionWatchersByIdentifier(&provisionWatchers, "name", "invalid") + if err != nil { + t.Fatalf("Error getting provisionWatchers %v", err) + } + if len(provisionWatchers) != 0 { + t.Fatalf("There should be 0 provisionWatchers instead of %d", len(provisionWatchers)) + } + + pw.Name = "name" + err = db.UpdateProvisionWatcher(pw) + if err != nil { + t.Fatalf("Error updating ProvisionWatcher %v", err) + } + + pw.Id = "INVALID" + err = db.UpdateProvisionWatcher(pw) + if err == nil { + t.Fatalf("Should return error") + } + + err = db.DeleteProvisionWatcher(pw) + if err == nil { + t.Fatalf("ProvisionWatcher should not be deleted") + } + + pw.Id = id + err = db.DeleteProvisionWatcher(pw) + if err != nil { + t.Fatalf("ProvisionWatcher should be deleted: %v", err) + } +} diff --git a/core/metadata/const.go b/core/metadata/const.go index 27b34557a2..2d34916f50 100644 --- a/core/metadata/const.go +++ b/core/metadata/const.go @@ -13,6 +13,8 @@ *******************************************************************************/ package metadata +import "github.com/edgexfoundry/edgex-go/core/metadata/interfaces" + // Struct used to pase the JSON configuration file type ConfigurationStruct struct { DBType string @@ -53,7 +55,7 @@ var configuration ConfigurationStruct = ConfigurationStruct{} // Needs to be ini var ( /* -------------- CONFIG for METADATA -------------------- */ - dbClient DBClient + dbClient interfaces.DBClient ) const ( diff --git a/core/metadata/init.go b/core/metadata/init.go index 662a023c0d..922d1bf846 100644 --- a/core/metadata/init.go +++ b/core/metadata/init.go @@ -18,6 +18,10 @@ import ( "strings" "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/db/memory" + "github.com/edgexfoundry/edgex-go/core/db/mongo" + "github.com/edgexfoundry/edgex-go/core/domain/enums" + "github.com/edgexfoundry/edgex-go/core/metadata/interfaces" "github.com/edgexfoundry/edgex-go/internal" consulclient "github.com/edgexfoundry/edgex-go/support/consul-client" logger "github.com/edgexfoundry/edgex-go/support/logging-client" @@ -48,6 +52,16 @@ func ConnectToConsul(conf ConfigurationStruct) error { return nil } +func getDatabase(dbType string, config db.Configuration) (interfaces.DBClient, error) { + switch dbType { + case enums.MongoStr: + return mongo.NewClient(config), nil + case enums.MemoryStr: + return &memory.MemDB{}, nil + } + return nil, db.ErrNotFound +} + func Init(conf ConfigurationStruct, l logger.LoggingClient) error { loggingClient = l configuration = conf diff --git a/core/metadata/dbOps.go b/core/metadata/interfaces/dbOps.go similarity index 87% rename from core/metadata/dbOps.go rename to core/metadata/interfaces/dbOps.go index 1cf0f29a0e..ac68b31847 100644 --- a/core/metadata/dbOps.go +++ b/core/metadata/interfaces/dbOps.go @@ -11,13 +11,11 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package metadata +package interfaces import ( - "github.com/edgexfoundry/edgex-go/core/db" - "github.com/edgexfoundry/edgex-go/core/db/mongo" - "github.com/edgexfoundry/edgex-go/core/domain/enums" "github.com/edgexfoundry/edgex-go/core/domain/models" + "gopkg.in/mgo.v2/bson" ) type DBClient interface { @@ -62,7 +60,7 @@ type DBClient interface { GetDevicesByProfileId(d *[]models.Device, pid string) error GetDevicesByServiceId(d *[]models.Device, sid string) error GetDevicesByAddressableId(d *[]models.Device, aid string) error - GetDevicesWithLabel(d *[]models.Device, l []string) error + GetDevicesWithLabel(d *[]models.Device, l string) error AddDevice(d *models.Device) error DeleteDevice(d models.Device) error UpdateDeviceProfile(dp *models.DeviceProfile) error @@ -71,13 +69,15 @@ type DBClient interface { GetDeviceProfileById(d *models.DeviceProfile, id string) error DeleteDeviceProfile(dp models.DeviceProfile) error GetDeviceProfilesByModel(dp *[]models.DeviceProfile, m string) error - GetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l []string) error + GetDeviceProfilesWithLabel(dp *[]models.DeviceProfile, l string) error GetDeviceProfilesByManufacturerModel(dp *[]models.DeviceProfile, man string, mod string) error GetDeviceProfilesByManufacturer(dp *[]models.DeviceProfile, man string) error GetDeviceProfileByName(dp *models.DeviceProfile, n string) error + GetDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error + // Addressable UpdateAddressable(ra *models.Addressable, r *models.Addressable) error - AddAddressable(a *models.Addressable) error + AddAddressable(a *models.Addressable) (bson.ObjectId, error) GetAddressableById(a *models.Addressable, id string) error GetAddressableByName(a *models.Addressable, n string) error GetAddressablesByTopic(a *[]models.Addressable, t string) error @@ -90,7 +90,7 @@ type DBClient interface { // Device service UpdateDeviceService(ds models.DeviceService) error GetDeviceServicesByAddressableId(d *[]models.DeviceService, id string) error - GetDeviceServicesWithLabel(d *[]models.DeviceService, l []string) error + GetDeviceServicesWithLabel(d *[]models.DeviceService, l string) error GetDeviceServiceById(d *models.DeviceService, id string) error GetDeviceServiceByName(d *models.DeviceService, n string) error GetAllDeviceServices(d *[]models.DeviceService) error @@ -101,7 +101,7 @@ type DBClient interface { GetProvisionWatcherById(pw *models.ProvisionWatcher, id string) error GetAllProvisionWatchers(pw *[]models.ProvisionWatcher) error GetProvisionWatcherByName(pw *models.ProvisionWatcher, n string) error - GetProvisionWatcherByProfileId(pw *[]models.ProvisionWatcher, id string) error + GetProvisionWatchersByProfileId(pw *[]models.ProvisionWatcher, id string) error GetProvisionWatchersByServiceId(pw *[]models.ProvisionWatcher, id string) error GetProvisionWatchersByIdentifier(pw *[]models.ProvisionWatcher, k string, v string) error AddProvisionWatcher(pw *models.ProvisionWatcher) error @@ -110,20 +110,9 @@ type DBClient interface { // Command GetCommandById(c *models.Command, id string) error - GetCommandByName(d *[]models.Command, id string) error + GetCommandByName(c *[]models.Command, id string) error AddCommand(c *models.Command) error GetAllCommands(d *[]models.Command) error UpdateCommand(c *models.Command, r *models.Command) error DeleteCommandById(id string) error - - GetDeviceProfilesUsingCommand(dp *[]models.DeviceProfile, c models.Command) error -} - -func getDatabase(dbType string, config db.Configuration) (DBClient, error) { - switch dbType { - case enums.MongoStr: - return mongo.NewClient(config), nil - case enums.MemoryStr: - } - return nil, db.ErrNotFound } diff --git a/core/metadata/rest_addressable.go b/core/metadata/rest_addressable.go index 2ed3285e91..d86d01e1da 100644 --- a/core/metadata/rest_addressable.go +++ b/core/metadata/rest_addressable.go @@ -24,6 +24,7 @@ import ( "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/gorilla/mux" "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" ) func restGetAllAddressables(w http.ResponseWriter, _ *http.Request) { @@ -62,8 +63,8 @@ func restAddAddressable(w http.ResponseWriter, r *http.Request) { return } } - - err = dbClient.AddAddressable(&a) + var id bson.ObjectId + id, err = dbClient.AddAddressable(&a) if err != nil { if err == db.ErrNotUnique { http.Error(w, "Duplicate name for addressable", http.StatusConflict) @@ -78,7 +79,7 @@ func restAddAddressable(w http.ResponseWriter, r *http.Request) { notifyAddressableAssociates(a, http.MethodPost) w.WriteHeader(http.StatusOK) - w.Write([]byte(a.Id.Hex())) + w.Write([]byte(id.Hex())) } // Update addressable by ID or name (ID used first) diff --git a/core/metadata/rest_device.go b/core/metadata/rest_device.go index 3045daa5b4..deba04ef20 100644 --- a/core/metadata/rest_device.go +++ b/core/metadata/rest_device.go @@ -286,11 +286,8 @@ func restGetDevicesWithLabel(w http.ResponseWriter, r *http.Request) { return } - var labels []string - labels = append(labels, label) - res := make([]models.Device, 0) - err = dbClient.GetDevicesWithLabel(&res, labels) + err = dbClient.GetDevicesWithLabel(&res, label) if err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) diff --git a/core/metadata/rest_deviceprofile.go b/core/metadata/rest_deviceprofile.go index ee3a814efe..69e4276c3c 100644 --- a/core/metadata/rest_deviceprofile.go +++ b/core/metadata/rest_deviceprofile.go @@ -342,7 +342,7 @@ func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error { // Check if the device profile is still in use by provision watchers var pw []models.ProvisionWatcher - if err := dbClient.GetProvisionWatcherByProfileId(&pw, dp.Id.Hex()); err != nil { + if err := dbClient.GetProvisionWatchersByProfileId(&pw, dp.Id.Hex()); err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) return err } @@ -474,10 +474,8 @@ func restGetProfileWithLabel(w http.ResponseWriter, r *http.Request) { return } - var labels []string - labels = append(labels, label) res := make([]models.DeviceProfile, 0) - if err := dbClient.GetDeviceProfilesWithLabel(&res, labels); err != nil { + if err := dbClient.GetDeviceProfilesWithLabel(&res, label); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return diff --git a/core/metadata/rest_deviceservice.go b/core/metadata/rest_deviceservice.go index 165633b0ac..7d26cad350 100644 --- a/core/metadata/rest_deviceservice.go +++ b/core/metadata/rest_deviceservice.go @@ -94,8 +94,8 @@ func restAddDeviceService(w http.ResponseWriter, r *http.Request) { if err != nil { if err != mgo.ErrNotFound { http.Error(w, err.Error(), http.StatusServiceUnavailable) + loggingClient.Error(err.Error(), "") } - loggingClient.Error(err.Error(), "") } else { // There wasn't an error - found the addressable foundAddressable = true @@ -391,11 +391,9 @@ func restGetServiceWithLabel(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusServiceUnavailable) return } - var ls []string - ls = append(ls, l) res := make([]models.DeviceService, 0) - if err := dbClient.GetDeviceServicesWithLabel(&res, ls); err != nil { + if err := dbClient.GetDeviceServicesWithLabel(&res, l); err != nil { loggingClient.Error(err.Error(), "") http.Error(w, err.Error(), http.StatusServiceUnavailable) return diff --git a/core/metadata/rest_provisionwatcher.go b/core/metadata/rest_provisionwatcher.go index a1b0970cc6..8bdd0840dc 100644 --- a/core/metadata/rest_provisionwatcher.go +++ b/core/metadata/rest_provisionwatcher.go @@ -171,7 +171,7 @@ func restGetProvisionWatchersByProfileId(w http.ResponseWriter, r *http.Request) } res := make([]models.ProvisionWatcher, 0) - err := dbClient.GetProvisionWatcherByProfileId(&res, pid) + err := dbClient.GetProvisionWatchersByProfileId(&res, pid) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") @@ -204,7 +204,7 @@ func restGetProvisionWatchersByProfileName(w http.ResponseWriter, r *http.Reques } res := make([]models.ProvisionWatcher, 0) - err = dbClient.GetProvisionWatcherByProfileId(&res, dp.Id.Hex()) + err = dbClient.GetProvisionWatchersByProfileId(&res, dp.Id.Hex()) if err != nil { http.Error(w, err.Error(), http.StatusServiceUnavailable) loggingClient.Error("Problem getting provision watcher: "+err.Error(), "") From d6b259a0a65b44ee1cad43509606021d12fbd93e Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Wed, 13 Jun 2018 15:33:06 +0200 Subject: [PATCH 06/10] Renamed some files Also made some types privates Signed-off-by: Federico Claramonte --- .../db/influx/{influx-client.go => client.go} | 0 .../db/memory/{memory-database.go => data.go} | 0 ...memory-database_test.go => memory_test.go} | 0 .../{memory-metadata.go => metadata.go} | 0 core/db/mongo/{mongo-client.go => client.go} | 12 +++--- .../{mongo-client_test.go => client_test.go} | 6 +-- core/db/mongo/{mongo_device.go => device.go} | 14 +++---- ...ngo_deviceprofile.go => device_profile.go} | 30 ++++++------- ...ngo_deviceservice.go => device_service.go} | 6 +-- core/db/mongo/{mongoevent.go => event.go} | 6 +-- core/db/mongo/{mongoOps.go => metadata.go} | 42 +++++++++---------- ...ovisionwatcher.go => provision_watcher.go} | 10 ++--- ...ngo_scheduleevent.go => schedule_event.go} | 6 +-- core/db/test/{db.go => db_data.go} | 0 14 files changed, 66 insertions(+), 66 deletions(-) rename core/db/influx/{influx-client.go => client.go} (100%) rename core/db/memory/{memory-database.go => data.go} (100%) rename core/db/memory/{memory-database_test.go => memory_test.go} (100%) rename core/db/memory/{memory-metadata.go => metadata.go} (100%) rename core/db/mongo/{mongo-client.go => client.go} (98%) rename core/db/mongo/{mongo-client_test.go => client_test.go} (96%) rename core/db/mongo/{mongo_device.go => device.go} (95%) rename core/db/mongo/{mongo_deviceprofile.go => device_profile.go} (79%) rename core/db/mongo/{mongo_deviceservice.go => device_service.go} (96%) rename core/db/mongo/{mongoevent.go => event.go} (96%) rename core/db/mongo/{mongoOps.go => metadata.go} (97%) rename core/db/mongo/{mongo_provisionwatcher.go => provision_watcher.go} (94%) rename core/db/mongo/{mongo_scheduleevent.go => schedule_event.go} (95%) rename core/db/test/{db.go => db_data.go} (100%) diff --git a/core/db/influx/influx-client.go b/core/db/influx/client.go similarity index 100% rename from core/db/influx/influx-client.go rename to core/db/influx/client.go diff --git a/core/db/memory/memory-database.go b/core/db/memory/data.go similarity index 100% rename from core/db/memory/memory-database.go rename to core/db/memory/data.go diff --git a/core/db/memory/memory-database_test.go b/core/db/memory/memory_test.go similarity index 100% rename from core/db/memory/memory-database_test.go rename to core/db/memory/memory_test.go diff --git a/core/db/memory/memory-metadata.go b/core/db/memory/metadata.go similarity index 100% rename from core/db/memory/memory-metadata.go rename to core/db/memory/metadata.go diff --git a/core/db/mongo/mongo-client.go b/core/db/mongo/client.go similarity index 98% rename from core/db/mongo/mongo-client.go rename to core/db/mongo/client.go index 1b45952910..8cfe982f27 100644 --- a/core/db/mongo/mongo-client.go +++ b/core/db/mongo/client.go @@ -23,7 +23,7 @@ import ( "gopkg.in/mgo.v2/bson" ) -var currentMongoClient *MongoClient // Singleton used so that MongoEvent can use it to de-reference readings +var currentMongoClient *MongoClient // Singleton used so that mongoEvent can use it to de-reference readings /* Core data client @@ -99,7 +99,7 @@ func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { } // Handle DBRefs - me := MongoEvent{Event: *e} + me := mongoEvent{Event: *e} // Add the event err := s.DB(mc.database.Name).C(db.EventsCollection).Insert(me) @@ -120,7 +120,7 @@ func (mc *MongoClient) UpdateEvent(e models.Event) error { e.Modified = time.Now().UnixNano() / int64(time.Millisecond) // Handle DBRef - me := MongoEvent{Event: e} + me := mongoEvent{Event: e} err := s.DB(mc.database.Name).C(db.EventsCollection).UpdateId(me.ID, me) if err == mgo.ErrNotFound { @@ -217,7 +217,7 @@ func (mc *MongoClient) getEvents(q bson.M) ([]models.Event, error) { defer s.Close() // Handle DBRefs - var me []MongoEvent + var me []mongoEvent events := []models.Event{} err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).All(&me) if err != nil { @@ -238,7 +238,7 @@ func (mc *MongoClient) getEventsLimit(q bson.M, limit int) ([]models.Event, erro defer s.Close() // Handle DBRefs - var me []MongoEvent + var me []mongoEvent events := []models.Event{} // Check if limit is 0 @@ -265,7 +265,7 @@ func (mc *MongoClient) getEvent(q bson.M) (models.Event, error) { defer s.Close() // Handle DBRef - var me MongoEvent + var me mongoEvent err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).One(&me) if err == mgo.ErrNotFound { return me.Event, db.ErrNotFound diff --git a/core/db/mongo/mongo-client_test.go b/core/db/mongo/client_test.go similarity index 96% rename from core/db/mongo/mongo-client_test.go rename to core/db/mongo/client_test.go index 84549a2085..98426f59cd 100644 --- a/core/db/mongo/mongo-client_test.go +++ b/core/db/mongo/client_test.go @@ -81,13 +81,13 @@ func BenchmarkMongoDB(b *testing.B) { b.Log("This benchmark needs to have a running mongo on localhost") - config := DBConfiguration{ - DbType: MONGO, + config := db.Configuration{ Host: "0.0.0.0", Port: 27017, DatabaseName: "coredata", Timeout: 1000, } + mongo := NewClient(config) - benchmarkDB(b, config) + test.BenchmarkDB(b, mongo) } diff --git a/core/db/mongo/mongo_device.go b/core/db/mongo/device.go similarity index 95% rename from core/db/mongo/mongo_device.go rename to core/db/mongo/device.go index 0ba3f12a71..fc105f4ec1 100644 --- a/core/db/mongo/mongo_device.go +++ b/core/db/mongo/device.go @@ -22,13 +22,13 @@ import ( // Internal version of the device struct // Use this to handle DBRef -type MongoDevice struct { +type mongoDevice struct { models.Device `bson:",inline"` } // Struct to hold the result of GetBSON // This struct is used by MongoDeviceManager so that it can call GetBSON explicitly on MongoDevice -type MongoDeviceBSON struct { +type mongoDeviceBSON struct { models.DescribedObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` Name string `bson:"name"` // Unique name for identifying a device @@ -44,8 +44,8 @@ type MongoDeviceBSON struct { } // Custom marshaling into mongo -func (md MongoDevice) GetBSON() (interface{}, error) { - return MongoDeviceBSON{ +func (md mongoDevice) GetBSON() (interface{}, error) { + return mongoDeviceBSON{ DescribedObject: md.DescribedObject, Id: md.Id, Name: md.Name, @@ -62,7 +62,7 @@ func (md MongoDevice) GetBSON() (interface{}, error) { } // Custom unmarshaling out of mongo -func (md *MongoDevice) SetBSON(raw bson.Raw) error { +func (md *mongoDevice) SetBSON(raw bson.Raw) error { decoded := new(struct { models.DescribedObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` @@ -107,8 +107,8 @@ func (md *MongoDevice) SetBSON(raw bson.Raw) error { dpCol := s.DB(m.database.Name).C(db.DeviceProfile) var a models.Addressable - var mdp MongoDeviceProfile - var mds MongoDeviceService + var mdp mongoDeviceProfile + var mds mongoDeviceService err = addCol.Find(bson.M{"_id": decoded.Addressable.Id}).One(&a) if err != nil { diff --git a/core/db/mongo/mongo_deviceprofile.go b/core/db/mongo/device_profile.go similarity index 79% rename from core/db/mongo/mongo_deviceprofile.go rename to core/db/mongo/device_profile.go index 7533ce71b2..4442b60adc 100644 --- a/core/db/mongo/mongo_deviceprofile.go +++ b/core/db/mongo/device_profile.go @@ -22,12 +22,12 @@ import ( // Internal version of the device profile struct // Use this to handle DBRef -type MongoDeviceProfile struct { +type mongoDeviceProfile struct { models.DeviceProfile } // Custom marshaling into mongo -func (mdp MongoDeviceProfile) GetBSON() (interface{}, error) { +func (mdp mongoDeviceProfile) GetBSON() (interface{}, error) { // Get the commands from the device profile and turn them into DBRef objects var dbRefs []mgo.DBRef for _, command := range mdp.Commands { @@ -59,21 +59,21 @@ func (mdp MongoDeviceProfile) GetBSON() (interface{}, error) { }, nil } -type Temp struct { - models.DescribedObject `bson:",inline"` - Id bson.ObjectId `bson:"_id,omitempty"` - Name string `bson:"name"` // Non-database identifier (must be unique) - Manufacturer string `bson:"manufacturer"` // Manufacturer of the device - Model string `bson:"model"` // Model of the device - Labels []string `bson:"labels"` // Labels used to search for groups of profiles - Objects interface{} `bson:"objects"` // JSON data that the device service uses to communicate with devices with this profile - DeviceResources []models.DeviceObject `bson:"deviceResources"` - Resources []models.ProfileResource `bson:"resources"` - Commands []mgo.DBRef `bson:"commands"` // List of commands to Get/Put information for devices associated with this profile -} +// type temp struct { +// models.DescribedObject `bson:",inline"` +// Id bson.ObjectId `bson:"_id,omitempty"` +// Name string `bson:"name"` // Non-database identifier (must be unique) +// Manufacturer string `bson:"manufacturer"` // Manufacturer of the device +// Model string `bson:"model"` // Model of the device +// Labels []string `bson:"labels"` // Labels used to search for groups of profiles +// Objects interface{} `bson:"objects"` // JSON data that the device service uses to communicate with devices with this profile +// DeviceResources []models.DeviceObject `bson:"deviceResources"` +// Resources []models.ProfileResource `bson:"resources"` +// Commands []mgo.DBRef `bson:"commands"` // List of commands to Get/Put information for devices associated with this profile +// } // Custom unmarshaling out of mongo -func (mdp *MongoDeviceProfile) SetBSON(raw bson.Raw) error { +func (mdp *mongoDeviceProfile) SetBSON(raw bson.Raw) error { decoded := new(struct { models.DescribedObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` diff --git a/core/db/mongo/mongo_deviceservice.go b/core/db/mongo/device_service.go similarity index 96% rename from core/db/mongo/mongo_deviceservice.go rename to core/db/mongo/device_service.go index f22381b28a..2baa598c69 100644 --- a/core/db/mongo/mongo_deviceservice.go +++ b/core/db/mongo/device_service.go @@ -22,12 +22,12 @@ import ( // Internal version of the device service struct // Use this to handle DBRef -type MongoDeviceService struct { +type mongoDeviceService struct { models.DeviceService } // Custom marshaling into mongo -func (mds MongoDeviceService) GetBSON() (interface{}, error) { +func (mds mongoDeviceService) GetBSON() (interface{}, error) { return struct { models.DescribedObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` @@ -52,7 +52,7 @@ func (mds MongoDeviceService) GetBSON() (interface{}, error) { } // Custom unmarshaling out of mongo -func (mds *MongoDeviceService) SetBSON(raw bson.Raw) error { +func (mds *mongoDeviceService) SetBSON(raw bson.Raw) error { decoded := new(struct { models.DescribedObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` diff --git a/core/db/mongo/mongoevent.go b/core/db/mongo/event.go similarity index 96% rename from core/db/mongo/mongoevent.go rename to core/db/mongo/event.go index 0ef3450af9..9f2017ee88 100644 --- a/core/db/mongo/mongoevent.go +++ b/core/db/mongo/event.go @@ -21,12 +21,12 @@ import ( ) // Struct that wraps an event to handle DBRefs -type MongoEvent struct { +type mongoEvent struct { models.Event } // Custom marshaling into mongo -func (me MongoEvent) GetBSON() (interface{}, error) { +func (me mongoEvent) GetBSON() (interface{}, error) { // Turn the readings into DBRef objects var readings []mgo.DBRef for _, reading := range me.Readings { @@ -56,7 +56,7 @@ func (me MongoEvent) GetBSON() (interface{}, error) { } // Custom unmarshaling out of mongo -func (me *MongoEvent) SetBSON(raw bson.Raw) error { +func (me *mongoEvent) SetBSON(raw bson.Raw) error { decoded := new(struct { ID bson.ObjectId `bson:"_id,omitempty"` Pushed int64 `bson:"pushed"` diff --git a/core/db/mongo/mongoOps.go b/core/db/mongo/metadata.go similarity index 97% rename from core/db/mongo/mongoOps.go rename to core/db/mongo/metadata.go index 07ea1fb06b..ec555cdfe9 100644 --- a/core/db/mongo/mongoOps.go +++ b/core/db/mongo/metadata.go @@ -66,7 +66,7 @@ func (m *MongoClient) UpdateScheduleEvent(se models.ScheduleEvent) error { se.Modified = makeTimestamp() // Handle DBRefs - mse := MongoScheduleEvent{ScheduleEvent: se} + mse := mongoScheduleEvent{ScheduleEvent: se} return col.UpdateId(se.Id, mse) } @@ -87,7 +87,7 @@ func (m *MongoClient) AddScheduleEvent(se *models.ScheduleEvent) error { se.Id = bson.NewObjectId() // Handle DBRefs - mse := MongoScheduleEvent{ScheduleEvent: *se} + mse := mongoScheduleEvent{ScheduleEvent: *se} return col.Insert(mse) } @@ -132,7 +132,7 @@ func (m *MongoClient) GetScheduleEvent(se *models.ScheduleEvent, q bson.M) error col := s.DB(m.database.Name).C(db.ScheduleEvent) // Handle DBRef - var mse MongoScheduleEvent + var mse mongoScheduleEvent err := col.Find(q).One(&mse) if err != nil { @@ -150,7 +150,7 @@ func (m *MongoClient) GetScheduleEvents(se *[]models.ScheduleEvent, q bson.M) er col := s.DB(m.database.Name).C(db.ScheduleEvent) // Handle the DBRef - var mses []MongoScheduleEvent + var mses []mongoScheduleEvent err := col.Find(q).Sort("queryts").All(&mses) if err != nil { @@ -325,7 +325,7 @@ func (m *MongoClient) AddDevice(d *models.Device) error { d.Id = bson.NewObjectId() // Wrap the device in MongoDevice (For DBRefs) - md := MongoDevice{Device: *d} + md := mongoDevice{Device: *d} return col.Insert(md) } @@ -336,7 +336,7 @@ func (m *MongoClient) UpdateDevice(rd models.Device) error { c := s.DB(m.database.Name).C(db.Device) // Copy over the DBRefs - md := MongoDevice{Device: rd} + md := mongoDevice{Device: rd} return c.UpdateId(rd.Id, md) } @@ -399,7 +399,7 @@ func (m *MongoClient) GetDevices(d *[]models.Device, q bson.M) error { s := m.session.Copy() defer s.Close() col := s.DB(m.database.Name).C(db.Device) - mds := []MongoDevice{} + mds := []mongoDevice{} err := col.Find(q).Sort("queryts").All(&mds) if err != nil { @@ -418,7 +418,7 @@ func (m *MongoClient) GetDevice(d *models.Device, q bson.M) error { s := m.session.Copy() defer s.Close() col := s.DB(m.database.Name).C(db.Device) - md := MongoDevice{} + md := mongoDevice{} err := col.Find(q).One(&md) if err != nil { @@ -470,7 +470,7 @@ func (m *MongoClient) GetDeviceProfiles(d *[]models.DeviceProfile, q bson.M) err col := s.DB(m.database.Name).C(db.DeviceProfile) // Handle the DBRefs - var mdps []MongoDeviceProfile + var mdps []mongoDeviceProfile err := col.Find(q).Sort("queryts").All(&mdps) if err != nil { return err @@ -491,7 +491,7 @@ func (m *MongoClient) GetDeviceProfile(d *models.DeviceProfile, q bson.M) error col := s.DB(m.database.Name).C(db.DeviceProfile) // Handle the DBRefs - var mdp MongoDeviceProfile + var mdp mongoDeviceProfile err := col.Find(q).One(&mdp) if err != nil { return err @@ -522,7 +522,7 @@ func (m *MongoClient) AddDeviceProfile(dp *models.DeviceProfile) error { dp.Modified = ts dp.Id = bson.NewObjectId() - mdp := MongoDeviceProfile{DeviceProfile: *dp} + mdp := mongoDeviceProfile{DeviceProfile: *dp} return col.Insert(mdp) } @@ -532,7 +532,7 @@ func (m *MongoClient) UpdateDeviceProfile(dp *models.DeviceProfile) error { defer s.Close() c := s.DB(m.database.Name).C(db.DeviceProfile) - mdp := MongoDeviceProfile{DeviceProfile: *dp} + mdp := mongoDeviceProfile{DeviceProfile: *dp} mdp.Modified = makeTimestamp() return c.UpdateId(mdp.Id, mdp) @@ -708,7 +708,7 @@ func (m *MongoClient) GetDeviceServices(d *[]models.DeviceService, q bson.M) err s := m.session.Copy() defer s.Close() col := s.DB(m.database.Name).C(db.DeviceService) - mdss := []MongoDeviceService{} + mdss := []mongoDeviceService{} err := col.Find(q).Sort("queryts").All(&mdss) if err != nil { return err @@ -724,7 +724,7 @@ func (m *MongoClient) GetDeviceService(d *models.DeviceService, q bson.M) error s := m.session.Copy() defer s.Close() col := s.DB(m.database.Name).C(db.DeviceService) - mds := MongoDeviceService{} + mds := mongoDeviceService{} err := col.Find(q).One(&mds) if err != nil { return err @@ -745,8 +745,8 @@ func (m *MongoClient) AddDeviceService(d *models.DeviceService) error { d.Modified = ts d.Id = bson.NewObjectId() - // MongoDeviceService handles the DBRefs - mds := MongoDeviceService{DeviceService: *d} + // mongoDeviceService handles the DBRefs + mds := mongoDeviceService{DeviceService: *d} return col.Insert(mds) } @@ -758,7 +758,7 @@ func (m *MongoClient) UpdateDeviceService(deviceService models.DeviceService) er deviceService.Modified = makeTimestamp() // Handle DBRefs - mds := MongoDeviceService{DeviceService: deviceService} + mds := mongoDeviceService{DeviceService: deviceService} return c.UpdateId(deviceService.Id, mds) } @@ -812,7 +812,7 @@ func (m *MongoClient) GetProvisionWatcher(pw *models.ProvisionWatcher, q bson.M) col := s.DB(m.database.Name).C(db.ProvisionWatcher) // Handle DBRefs - var mpw MongoProvisionWatcher + var mpw mongoProvisionWatcher err := col.Find(q).One(&mpw) if err != nil { @@ -830,7 +830,7 @@ func (m *MongoClient) GetProvisionWatchers(pw *[]models.ProvisionWatcher, q bson col := s.DB(m.database.Name).C(db.ProvisionWatcher) // Handle DBRefs - var mpws []MongoProvisionWatcher + var mpws []mongoProvisionWatcher err := col.Find(q).Sort("queryts").All(&mpws) if err != nil { @@ -885,7 +885,7 @@ func (m *MongoClient) AddProvisionWatcher(pw *models.ProvisionWatcher) error { pw.Id = bson.NewObjectId() // Handle DBRefs - mpw := MongoProvisionWatcher{ProvisionWatcher: *pw} + mpw := mongoProvisionWatcher{ProvisionWatcher: *pw} return col.Insert(mpw) } @@ -898,7 +898,7 @@ func (m *MongoClient) UpdateProvisionWatcher(pw models.ProvisionWatcher) error { pw.Modified = makeTimestamp() // Handle DBRefs - mpw := MongoProvisionWatcher{ProvisionWatcher: pw} + mpw := mongoProvisionWatcher{ProvisionWatcher: pw} return c.UpdateId(mpw.Id, mpw) } diff --git a/core/db/mongo/mongo_provisionwatcher.go b/core/db/mongo/provision_watcher.go similarity index 94% rename from core/db/mongo/mongo_provisionwatcher.go rename to core/db/mongo/provision_watcher.go index 9b22bb74c3..0ee18a305b 100644 --- a/core/db/mongo/mongo_provisionwatcher.go +++ b/core/db/mongo/provision_watcher.go @@ -22,12 +22,12 @@ import ( // Internal version of the provision watcher struct // Use this to handle DBRef -type MongoProvisionWatcher struct { +type mongoProvisionWatcher struct { models.ProvisionWatcher } // Custom marshaling into mongo -func (mpw MongoProvisionWatcher) GetBSON() (interface{}, error) { +func (mpw mongoProvisionWatcher) GetBSON() (interface{}, error) { return struct { models.BaseObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` @@ -48,7 +48,7 @@ func (mpw MongoProvisionWatcher) GetBSON() (interface{}, error) { } // Custom unmarshaling out of mongo -func (mpw *MongoProvisionWatcher) SetBSON(raw bson.Raw) error { +func (mpw *mongoProvisionWatcher) SetBSON(raw bson.Raw) error { decoded := new(struct { models.BaseObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` @@ -82,8 +82,8 @@ func (mpw *MongoProvisionWatcher) SetBSON(raw bson.Raw) error { profCol := s.DB(m.database.Name).C(db.DeviceProfile) servCol := s.DB(m.database.Name).C(db.DeviceService) - var mdp MongoDeviceProfile - var mds MongoDeviceService + var mdp mongoDeviceProfile + var mds mongoDeviceService if err := profCol.FindId(decoded.Profile.Id).One(&mdp); err != nil { return err diff --git a/core/db/mongo/mongo_scheduleevent.go b/core/db/mongo/schedule_event.go similarity index 95% rename from core/db/mongo/mongo_scheduleevent.go rename to core/db/mongo/schedule_event.go index 185593371d..a2bd8c9ec8 100644 --- a/core/db/mongo/mongo_scheduleevent.go +++ b/core/db/mongo/schedule_event.go @@ -22,12 +22,12 @@ import ( // Internal version of the schedule event struct // Use this to handle DBRef -type MongoScheduleEvent struct { +type mongoScheduleEvent struct { models.ScheduleEvent } // Custom marshaling into mongo -func (mse MongoScheduleEvent) GetBSON() (interface{}, error) { +func (mse mongoScheduleEvent) GetBSON() (interface{}, error) { return struct { models.BaseObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` @@ -48,7 +48,7 @@ func (mse MongoScheduleEvent) GetBSON() (interface{}, error) { } // Custom unmarshaling out of mongo -func (mse *MongoScheduleEvent) SetBSON(raw bson.Raw) error { +func (mse *mongoScheduleEvent) SetBSON(raw bson.Raw) error { decoded := new(struct { models.BaseObject `bson:",inline"` Id bson.ObjectId `bson:"_id,omitempty"` diff --git a/core/db/test/db.go b/core/db/test/db_data.go similarity index 100% rename from core/db/test/db.go rename to core/db/test/db_data.go From 52b7f2258785b19f74d1c34721c923ff020eaaf3 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Mon, 18 Jun 2018 11:10:30 +0200 Subject: [PATCH 07/10] core/db: create client.go, data.go and metadata.go for each database Signed-off-by: Federico Claramonte --- core/db/influx/client.go | 759 ------------------------------------ core/db/influx/data.go | 783 ++++++++++++++++++++++++++++++++++++++ core/db/memory/client.go | 50 +++ core/db/memory/data.go | 34 -- core/db/mongo/client.go | 568 ++------------------------- core/db/mongo/data.go | 561 +++++++++++++++++++++++++++ core/db/mongo/metadata.go | 31 -- 7 files changed, 1420 insertions(+), 1366 deletions(-) create mode 100644 core/db/influx/data.go create mode 100644 core/db/memory/client.go create mode 100644 core/db/mongo/data.go diff --git a/core/db/influx/client.go b/core/db/influx/client.go index ee8d6a1b3d..3301e8846c 100644 --- a/core/db/influx/client.go +++ b/core/db/influx/client.go @@ -18,13 +18,10 @@ import ( "encoding/json" "fmt" "strconv" - "strings" "time" "github.com/edgexfoundry/edgex-go/core/db" - "github.com/edgexfoundry/edgex-go/core/domain/models" "github.com/influxdata/influxdb/client/v2" - "gopkg.in/mgo.v2/bson" ) var currentInfluxClient *InfluxClient // Singleton used so that InfluxEvent can use it to de-reference readings @@ -103,141 +100,6 @@ func (ic *InfluxClient) CloseSession() { ic.Client.Close() } -// ******************************* EVENTS ********************************** - -// Return all the events -// UnexpectedError - failed to retrieve events from the database -// Sort the events in descending order by ID -func (ic *InfluxClient) Events() ([]models.Event, error) { - return ic.getEvents("") -} - -// Add a new event -// UnexpectedError - failed to add to database -// NoValueDescriptor - no existing value descriptor for a reading in the event -func (ic *InfluxClient) AddEvent(e *models.Event) (bson.ObjectId, error) { - e.Created = time.Now().UnixNano() / int64(time.Millisecond) - e.ID = bson.NewObjectId() - - // Add the event - err := ic.eventToDB(ic.Database, db.EventsCollection, e, true) - if err != nil { - return e.ID, err - } - - return e.ID, err -} - -// Update an event - do NOT update readings -// UnexpectedError - problem updating in database -// NotFound - no event with the ID was found -func (ic *InfluxClient) UpdateEvent(e models.Event) error { - e.Modified = time.Now().UnixNano() / int64(time.Millisecond) - - // Delete event - if err := ic.deleteById(db.EventsCollection, e.ID.Hex()); err != nil { - return err - } - - // Add the event - return ic.eventToDB(ic.Database, db.EventsCollection, &e, false) -} - -// Get an event by id -func (ic *InfluxClient) EventById(id string) (models.Event, error) { - if !bson.IsObjectIdHex(id) { - return models.Event{}, db.ErrInvalidObjectId - } - q := fmt.Sprintf("WHERE id = '%s'", id) - events, err := ic.getEvents(q) - if len(events) < 1 { - return models.Event{}, nil - } - return events[0], err -} - -// Get the number of events in Influx -func (ic *InfluxClient) EventCount() (int, error) { - query := fmt.Sprintf("SELECT COUNT(*) FROM %s", db.EventsCollection) - return ic.getCount(query) -} - -// Get the number of events in Influx for the device -func (ic *InfluxClient) EventCountByDeviceId(id string) (int, error) { - query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE device = '%s'", db.EventsCollection, id) - return ic.getCount(query) -} - -// Delete an event by ID and all of its readings -// 404 - Event not found -// 503 - Unexpected problems -func (ic *InfluxClient) DeleteEventById(id string) error { - return ic.deleteById(db.EventsCollection, id) -} - -// Get a list of events based on the device id and limit -func (ic *InfluxClient) EventsForDeviceLimit(id string, limit int) ([]models.Event, error) { - query := fmt.Sprintf("WHERE device = '%s' LIMIT %d", id, limit) - return ic.getEvents(query) -} - -// Get a list of events based on the device id -func (ic *InfluxClient) EventsForDevice(id string) ([]models.Event, error) { - query := fmt.Sprintf("WHERE device = '%s'", id) - return ic.getEvents(query) -} - -// Return a list of events whos creation time is between startTime and endTime -// Limit the number of results by limit -func (ic *InfluxClient) EventsByCreationTime(startTime, endTime int64, limit int) ([]models.Event, error) { - query := fmt.Sprintf("WHERE created >= %d AND created <= %d LIMIT %d", startTime, endTime, limit) - return ic.getEvents(query) -} - -// Get Events that are older than the given age (defined by age = now - created) -func (ic *InfluxClient) EventsOlderThanAge(age int64) ([]models.Event, error) { - expireDate := (time.Now().UnixNano() / int64(time.Millisecond)) - age - query := fmt.Sprintf("WHERE created < %d", expireDate) - return ic.getEvents(query) -} - -// Get all of the events that have been pushed -func (ic *InfluxClient) EventsPushed() ([]models.Event, error) { - query := fmt.Sprintf("WHERE pushed > 0") - return ic.getEvents(query) -} - -// Delete all of the readings and all of the events -func (ic *InfluxClient) ScrubAllEvents() error { - err := ic.deleteAll(db.ReadingsCollection) - if err != nil { - return err - } - - return ic.deleteAll(db.EventsCollection) -} - -// Get events for the passed query -func (ic *InfluxClient) getEvents(q string) ([]models.Event, error) { - events := []models.Event{} - query := fmt.Sprintf("SELECT * FROM %s %s", db.EventsCollection, q) - res, err := ic.queryDB(query) - if err != nil { - return events, err - } - - if len(res) == 1 { - if len(res[0].Series) == 1 { - events, err = parseEvents(res[0]) - if err != nil { - return events, err - } - } - } - - return events, nil -} - func (ic *InfluxClient) deleteById(collection string, id string) error { q := fmt.Sprintf("DROP SERIES FROM %s WHERE id = '%s'", collection, id) _, err := ic.queryDB(q) @@ -255,624 +117,3 @@ func (ic *InfluxClient) deleteAll(collection string) error { } return nil } - -func (ic *InfluxClient) eventToDB(dbStr string, collection string, e *models.Event, addReadings bool) error { - bp, err := client.NewBatchPoints(client.BatchPointsConfig{ - Database: dbStr, - Precision: "us", - }) - if err != nil { - return err - } - - var stringArray []string - for i := range e.Readings { - if addReadings == true { - e.Readings[i].Id = bson.NewObjectId() - e.Readings[i].Created = e.Created - e.Readings[i].Device = e.Device - - fields := map[string]interface{}{ - "pushed": e.Readings[i].Pushed, - "created": e.Readings[i].Created, - "origin": e.Readings[i].Origin, - "modified": e.Readings[i].Modified, - } - - tags := map[string]string{ - "id": e.Readings[i].Id.Hex(), - "device": e.Readings[i].Device, - "name": e.Readings[i].Name, - "value": e.Readings[i].Value, - } - - pt, err := client.NewPoint( - db.ReadingsCollection, - tags, - fields, - time.Now(), - ) - if err != nil { - return err - } - bp.AddPoint(pt) - } - stringArray = append(stringArray, e.Readings[i].Id.Hex()) - } - readings := strings.Join(stringArray, " ") - - fields := map[string]interface{}{ - "pushed": e.Pushed, - "created": e.Created, - "origin": e.Origin, - "modified": e.Modified, - "readings": readings, - } - - tags := map[string]string{ - "id": e.ID.Hex(), - "device": e.Device, - "event": e.Event, - } - - pt, err := client.NewPoint( - collection, - tags, - fields, - time.Now(), - ) - if err != nil { - return err - } - bp.AddPoint(pt) - return ic.Client.Write(bp) -} - -func parseEvents(res client.Result) ([]models.Event, error) { - var events []models.Event - for i, _ := range res.Series[0].Values { - var event models.Event - var readings []string - for j, col := range res.Series[0].Columns { - switch col { - case "id": - event.ID = bson.ObjectIdHex(res.Series[0].Values[i][j].(string)) - case "pushed": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return events, err - } - event.Pushed = n - case "created": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return events, err - } - event.Created = n - case "origin": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return events, err - } - event.Origin = n - case "modified": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return events, err - } - event.Modified = n - case "device": - if res.Series[0].Values[i][j] != nil { - event.Device = res.Series[0].Values[i][j].(string) - } - case "event": - if res.Series[0].Values[i][j] != nil { - event.Event = res.Series[0].Values[i][j].(string) - } - case "readings": - if res.Series[0].Values[i][j] != nil { - s := res.Series[0].Values[i][j].(string) - readings = strings.Split(s, " ") - } - } - } - for _, id := range readings { - reading, err := currentInfluxClient.ReadingById(id) - if err != nil { - return events, nil - } - event.Readings = append(event.Readings, reading) - } - - events = append(events, event) - } - return events, nil -} - -// ************************ READINGS ************************************ - -// Return a list of readings sorted by reading id -func (ic *InfluxClient) Readings() ([]models.Reading, error) { - return ic.getReadings("") -} - -// Post a new reading -func (ic *InfluxClient) AddReading(r models.Reading) (bson.ObjectId, error) { - // Get the reading ready - r.Id = bson.NewObjectId() - r.Created = time.Now().UnixNano() / int64(time.Millisecond) - err := ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) - return r.Id, err -} - -// Update a reading -// 404 - reading cannot be found -// 409 - Value descriptor doesn't exist -// 503 - unknown issues -func (ic *InfluxClient) UpdateReading(r models.Reading) error { - r.Modified = time.Now().UnixNano() / int64(time.Millisecond) - - // Delete reading - if err := ic.deleteById(db.ReadingsCollection, r.Id.Hex()); err != nil { - return err - } - - // Add the reading - return ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) -} - -// Get a reading by ID -func (ic *InfluxClient) ReadingById(id string) (models.Reading, error) { - // Check if the id is a id hex - if !bson.IsObjectIdHex(id) { - return models.Reading{}, db.ErrInvalidObjectId - } - - query := fmt.Sprintf("WHERE id = '%s'", id) - readings, err := ic.getReadings(query) - return readings[0], err -} - -// Get the count of readings in Influx -func (ic *InfluxClient) ReadingCount() (int, error) { - query := fmt.Sprintf("SELECT COUNT(*) FROM %s", db.ReadingsCollection) - return ic.getCount(query) -} - -// Delete a reading by ID -// 404 - can't find the reading with the given id -func (ic *InfluxClient) DeleteReadingById(id string) error { - return ic.deleteById(db.ReadingsCollection, id) -} - -// Return a list of readings for the given device (id or name) -// Sort the list of readings on creation date -func (ic *InfluxClient) ReadingsByDevice(id string, limit int) ([]models.Reading, error) { - query := fmt.Sprintf("WHERE device = '%s' LIMIT %d", id, limit) - return ic.getReadings(query) -} - -// Return a list of readings for the given value descriptor -// Limit by the given limit -func (ic *InfluxClient) ReadingsByValueDescriptor(name string, limit int) ([]models.Reading, error) { - query := fmt.Sprintf("WHERE name = '%s' LIMIT %d", name, limit) - return ic.getReadings(query) -} - -// Return a list of readings whose name is in the list of value descriptor names -func (ic *InfluxClient) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { - var readings []models.Reading - for _, name := range names { - query := fmt.Sprintf("WHERE name = '%s' LIMIT %d", name, limit) - rlist, err := ic.getReadings(query) - if err != nil { - return readings, err - } - readings = append(readings, rlist...) - } - return readings, nil -} - -// Return a list of readings whos creation time is in-between start and end -// Limit by the limit parameter -func (ic *InfluxClient) ReadingsByCreationTime(start, end int64, limit int) ([]models.Reading, error) { - query := fmt.Sprintf("WHERE created >= %d AND created <= %d LIMIT %d", start, end, limit) - return ic.getReadings(query) -} - -// Return a list of readings for a device filtered by the value descriptor and limited by the limit -// The readings are linked to the device through an event -func (ic *InfluxClient) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor string, limit int) ([]models.Reading, error) { - query := fmt.Sprintf("WHERE device = '%s' AND value = '%s' LIMIT %d", deviceId, valueDescriptor, limit) - return ic.getReadings(query) -} - -// Get readings for the passed query -func (ic *InfluxClient) getReadings(q string) ([]models.Reading, error) { - readings := []models.Reading{} - query := fmt.Sprintf("SELECT * FROM %s %s", db.ReadingsCollection, q) - res, err := ic.queryDB(query) - if err != nil { - return readings, err - } - - if len(res) == 1 { - if len(res[0].Series) == 1 { - readings, err = parseReadings(res[0]) - if err != nil { - return readings, err - } - } - } - - return readings, nil -} - -func (ic *InfluxClient) addReadingToDB(db string, collection string, r *models.Reading) error { - bp, err := client.NewBatchPoints(client.BatchPointsConfig{ - Database: db, - Precision: "us", - }) - if err != nil { - return err - } - fields := map[string]interface{}{ - "pushed": r.Pushed, - "created": r.Created, - "origin": r.Origin, - "modified": r.Modified, - } - - tags := map[string]string{ - "id": r.Id.Hex(), - "device": r.Device, - "name": r.Name, - "value": r.Value, - } - - pt, err := client.NewPoint( - collection, - tags, - fields, - time.Now(), - ) - if err != nil { - return err - } - bp.AddPoint(pt) - return ic.Client.Write(bp) -} - -func parseReadings(res client.Result) ([]models.Reading, error) { - var readings []models.Reading - for i, _ := range res.Series[0].Values { - var reading models.Reading - for j, col := range res.Series[0].Columns { - switch col { - case "id": - reading.Id = bson.ObjectIdHex(res.Series[0].Values[i][j].(string)) - case "pushed": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return readings, err - } - reading.Pushed = n - case "created": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return readings, err - } - reading.Created = n - case "origin": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return readings, err - } - reading.Origin = n - case "modified": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return readings, err - } - reading.Modified = n - case "device": - if res.Series[0].Values[i][j] != nil { - reading.Device = res.Series[0].Values[i][j].(string) - } - case "name": - if res.Series[0].Values[i][j] != nil { - reading.Name = res.Series[0].Values[i][j].(string) - } - case "value": - if res.Series[0].Values[i][j] != nil { - reading.Value = res.Series[0].Values[i][j].(string) - } - } - } - - readings = append(readings, reading) - } - return readings, nil -} - -// ************************* VALUE DESCRIPTORS ***************************** - -// Add a value descriptor -// 409 - Formatting is bad or it is not unique -// 503 - Unexpected -// TODO: Check for valid printf formatting -func (ic *InfluxClient) AddValueDescriptor(v models.ValueDescriptor) (bson.ObjectId, error) { - // Created/Modified now - v.Created = time.Now().UnixNano() / int64(time.Millisecond) - - // See if the name is unique and add the value descriptors - query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE 'name' = '%s'", db.ValueDescriptorCollection, v.Name) - num, err := ic.getCount(query) - if err != nil { - return v.Id, err - } - - // Duplicate name - if num != 0 { - return v.Id, db.ErrNotUnique - } - - // Set id - v.Id = bson.NewObjectId() - - // Add Value Descriptor - err = ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) - if err != nil { - return v.Id, err - } - - return v.Id, err -} - -// Return a list of all the value descriptors -// 513 Service Unavailable - database problems -func (ic *InfluxClient) ValueDescriptors() ([]models.ValueDescriptor, error) { - return ic.getValueDescriptors("") -} - -// Update a value descriptor -// First use the ID for identification, then the name -// TODO: Check for the valid printf formatting -// 404 not found if the value descriptor cannot be found by the identifiers -func (ic *InfluxClient) UpdateValueDescriptor(v models.ValueDescriptor) error { - // See if the name is unique if it changed - query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE id = '%s'", db.ValueDescriptorCollection, v.Id) - num, err := ic.getCount(query) - if err != nil { - return err - } - if num != 0 { - return db.ErrNotUnique - } - query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE name = '%s'", db.ValueDescriptorCollection, v.Name) - num, err = ic.getCount(query) - if err != nil { - return err - } - if num != 0 { - query = fmt.Sprintf("WHERE name = '%s'", v.Name) - err := ic.deleteValueDescriptorBy(query) - if err != nil { - return err - } - } - v.Modified = time.Now().UnixNano() / int64(time.Millisecond) - // Delete Value Descriptor - // Add Value Descriptor - return ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) -} - -// Delete the value descriptor based on the id -// Not found error if there isn't a value descriptor for the ID -// ValueDescriptorStillInUse if the value descriptor is still referenced by readings -func (ic *InfluxClient) DeleteValueDescriptorById(id string) error { - query := fmt.Sprintf("WHERE id = '%s'", id) - return ic.deleteValueDescriptorBy(query) -} - -// Return a value descriptor based on the name -// Can return null if no value descriptor is found -func (ic *InfluxClient) ValueDescriptorByName(name string) (models.ValueDescriptor, error) { - query := fmt.Sprintf("WHERE \"name\" = '%s'", name) - v, err := ic.getValueDescriptors(query) - if err != nil || len(v) < 1 { - var vret models.ValueDescriptor - return vret, err - } - return v[0], err -} - -// Return all of the value descriptors based on the names -func (ic *InfluxClient) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor, error) { - vList := []models.ValueDescriptor{} - - for _, name := range names { - query := fmt.Sprintf("WHERE name = '%s'", name) - v, err := ic.getValueDescriptors(query) - if err != nil || len(v) < 1 { - return []models.ValueDescriptor{}, err - } - vList = append(vList, v[0]) - } - - return vList, nil -} - -// Return a value descriptor based on the id -// Return NotFoundError if there is no value descriptor for the id -func (ic *InfluxClient) ValueDescriptorById(id string) (models.ValueDescriptor, error) { - if !bson.IsObjectIdHex(id) { - return models.ValueDescriptor{}, db.ErrInvalidObjectId - } - - query := fmt.Sprintf("WHERE id = '%s'", id) - v, err := ic.getValueDescriptors(query) - if err != nil || len(v) < 1 { - return models.ValueDescriptor{}, err - } - return v[0], err -} - -// Return all the value descriptors that match the UOM label -func (ic *InfluxClient) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescriptor, error) { - query := fmt.Sprintf("WHERE uomLabel = '%s'", uomLabel) - return ic.getValueDescriptors(query) -} - -// Return value descriptors based on if it has the label -func (ic *InfluxClient) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, error) { - query := fmt.Sprintf("WHERE label = '%s'", label) - return ic.getValueDescriptors(query) -} - -// Return value descriptors based on if it has the label -func (ic *InfluxClient) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, error) { - query := fmt.Sprintf("WHERE type = '%s'", t) - return ic.getValueDescriptors(query) -} - -// Delete all of the value descriptors -func (ic *InfluxClient) ScrubAllValueDescriptors() error { - return ic.deleteAll(db.ValueDescriptorCollection) -} - -func (ic *InfluxClient) deleteValueDescriptorBy(query string) error { - q := fmt.Sprintf("DELETE FROM %s %s", db.ValueDescriptorCollection, query) - _, err := ic.queryDB(q) - if err != nil { - return err - } - return nil -} - -// Get value descriptors for the passed query -func (ic *InfluxClient) getValueDescriptors(q string) ([]models.ValueDescriptor, error) { - vds := []models.ValueDescriptor{} - query := fmt.Sprintf("SELECT * FROM %s %s", db.ValueDescriptorCollection, q) - res, err := ic.queryDB(query) - if err != nil { - return vds, err - } - - if len(res) == 1 { - if len(res[0].Series) == 1 { - vds, err = parseValueDescriptors(res[0]) - if err != nil { - return vds, err - } - } - } - - return vds, nil -} - -func (ic *InfluxClient) addValueDescriptorToDB(db string, collection string, v *models.ValueDescriptor) error { - bp, err := client.NewBatchPoints(client.BatchPointsConfig{ - Database: db, - Precision: "us", - }) - if err != nil { - return err - } - fields := map[string]interface{}{ - "description": v.Description, - "created": v.Created, - "origin": v.Origin, - "modified": v.Modified, - "min": v.Min, - "max": v.Max, - "defaultvalue": v.DefaultValue, - "Labels": v.Labels, - } - - tags := map[string]string{ - "id": v.Id.Hex(), - "name": v.Name, - "UomLabel": v.UomLabel, - "type": v.Type, - "formatting": v.Formatting, - } - - pt, err := client.NewPoint( - collection, - tags, - fields, - time.Now(), - ) - if err != nil { - return err - } - bp.AddPoint(pt) - return ic.Client.Write(bp) -} - -func parseValueDescriptors(res client.Result) ([]models.ValueDescriptor, error) { - var vds []models.ValueDescriptor - for i, _ := range res.Series[0].Values { - var vd models.ValueDescriptor - for j, col := range res.Series[0].Columns { - switch col { - case "id": - vd.Id = bson.ObjectIdHex(res.Series[0].Values[i][j].(string)) - case "created": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return vds, err - } - vd.Created = n - case "origin": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return vds, err - } - vd.Origin = n - case "modified": - n, err := res.Series[0].Values[i][j].(json.Number).Int64() - if err != nil { - return vds, err - } - vd.Modified = n - case "name": - if res.Series[0].Values[i][j] != nil { - vd.Name = res.Series[0].Values[i][j].(string) - } - case "description": - if res.Series[0].Values[i][j] != nil { - vd.Description = res.Series[0].Values[i][j].(string) - } - case "min": - if res.Series[0].Values[i][j] != nil { - vd.Min = res.Series[0].Values[i][j].(string) - } - case "max": - if res.Series[0].Values[i][j] != nil { - vd.Max = res.Series[0].Values[i][j].(string) - } - case "type": - if res.Series[0].Values[i][j] != nil { - vd.Type = res.Series[0].Values[i][j].(string) - } - case "uomLabel": - if res.Series[0].Values[i][j] != nil { - vd.UomLabel = res.Series[0].Values[i][j].(string) - } - case "labels": - // ToDo set labels - strings := []string{"dummy"} - vd.Labels = strings - case "defalutvalue": - if res.Series[0].Values[i][j] != nil { - vd.DefaultValue = res.Series[0].Values[i][j].(string) - } - } - } - - vds = append(vds, vd) - } - return vds, nil -} diff --git a/core/db/influx/data.go b/core/db/influx/data.go new file mode 100644 index 0000000000..8ba7745385 --- /dev/null +++ b/core/db/influx/data.go @@ -0,0 +1,783 @@ +/******************************************************************************* + * Copyright 2017 Dell Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ + +package influx + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/domain/models" + client "github.com/influxdata/influxdb/client/v2" + "gopkg.in/mgo.v2/bson" +) + +// ******************************* EVENTS ********************************** + +// Return all the events +// UnexpectedError - failed to retrieve events from the database +// Sort the events in descending order by ID +func (ic *InfluxClient) Events() ([]models.Event, error) { + return ic.getEvents("") +} + +// Add a new event +// UnexpectedError - failed to add to database +// NoValueDescriptor - no existing value descriptor for a reading in the event +func (ic *InfluxClient) AddEvent(e *models.Event) (bson.ObjectId, error) { + e.Created = time.Now().UnixNano() / int64(time.Millisecond) + e.ID = bson.NewObjectId() + + // Add the event + err := ic.eventToDB(ic.Database, db.EventsCollection, e, true) + if err != nil { + return e.ID, err + } + + return e.ID, err +} + +// Update an event - do NOT update readings +// UnexpectedError - problem updating in database +// NotFound - no event with the ID was found +func (ic *InfluxClient) UpdateEvent(e models.Event) error { + e.Modified = time.Now().UnixNano() / int64(time.Millisecond) + + // Delete event + if err := ic.deleteById(db.EventsCollection, e.ID.Hex()); err != nil { + return err + } + + // Add the event + return ic.eventToDB(ic.Database, db.EventsCollection, &e, false) +} + +// Get an event by id +func (ic *InfluxClient) EventById(id string) (models.Event, error) { + if !bson.IsObjectIdHex(id) { + return models.Event{}, db.ErrInvalidObjectId + } + q := fmt.Sprintf("WHERE id = '%s'", id) + events, err := ic.getEvents(q) + if len(events) < 1 { + return models.Event{}, nil + } + return events[0], err +} + +// Get the number of events in Influx +func (ic *InfluxClient) EventCount() (int, error) { + query := fmt.Sprintf("SELECT COUNT(*) FROM %s", db.EventsCollection) + return ic.getCount(query) +} + +// Get the number of events in Influx for the device +func (ic *InfluxClient) EventCountByDeviceId(id string) (int, error) { + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE device = '%s'", db.EventsCollection, id) + return ic.getCount(query) +} + +// Delete an event by ID and all of its readings +// 404 - Event not found +// 503 - Unexpected problems +func (ic *InfluxClient) DeleteEventById(id string) error { + return ic.deleteById(db.EventsCollection, id) +} + +// Get a list of events based on the device id and limit +func (ic *InfluxClient) EventsForDeviceLimit(id string, limit int) ([]models.Event, error) { + query := fmt.Sprintf("WHERE device = '%s' LIMIT %d", id, limit) + return ic.getEvents(query) +} + +// Get a list of events based on the device id +func (ic *InfluxClient) EventsForDevice(id string) ([]models.Event, error) { + query := fmt.Sprintf("WHERE device = '%s'", id) + return ic.getEvents(query) +} + +// Return a list of events whos creation time is between startTime and endTime +// Limit the number of results by limit +func (ic *InfluxClient) EventsByCreationTime(startTime, endTime int64, limit int) ([]models.Event, error) { + query := fmt.Sprintf("WHERE created >= %d AND created <= %d LIMIT %d", startTime, endTime, limit) + return ic.getEvents(query) +} + +// Get Events that are older than the given age (defined by age = now - created) +func (ic *InfluxClient) EventsOlderThanAge(age int64) ([]models.Event, error) { + expireDate := (time.Now().UnixNano() / int64(time.Millisecond)) - age + query := fmt.Sprintf("WHERE created < %d", expireDate) + return ic.getEvents(query) +} + +// Get all of the events that have been pushed +func (ic *InfluxClient) EventsPushed() ([]models.Event, error) { + query := fmt.Sprintf("WHERE pushed > 0") + return ic.getEvents(query) +} + +// Delete all of the readings and all of the events +func (ic *InfluxClient) ScrubAllEvents() error { + err := ic.deleteAll(db.ReadingsCollection) + if err != nil { + return err + } + + return ic.deleteAll(db.EventsCollection) +} + +// Get events for the passed query +func (ic *InfluxClient) getEvents(q string) ([]models.Event, error) { + events := []models.Event{} + query := fmt.Sprintf("SELECT * FROM %s %s", db.EventsCollection, q) + res, err := ic.queryDB(query) + if err != nil { + return events, err + } + + if len(res) == 1 { + if len(res[0].Series) == 1 { + events, err = parseEvents(res[0]) + if err != nil { + return events, err + } + } + } + + return events, nil +} + +func (ic *InfluxClient) eventToDB(dbStr string, collection string, e *models.Event, addReadings bool) error { + bp, err := client.NewBatchPoints(client.BatchPointsConfig{ + Database: dbStr, + Precision: "us", + }) + if err != nil { + return err + } + + var stringArray []string + for i := range e.Readings { + if addReadings == true { + e.Readings[i].Id = bson.NewObjectId() + e.Readings[i].Created = e.Created + e.Readings[i].Device = e.Device + + fields := map[string]interface{}{ + "pushed": e.Readings[i].Pushed, + "created": e.Readings[i].Created, + "origin": e.Readings[i].Origin, + "modified": e.Readings[i].Modified, + } + + tags := map[string]string{ + "id": e.Readings[i].Id.Hex(), + "device": e.Readings[i].Device, + "name": e.Readings[i].Name, + "value": e.Readings[i].Value, + } + + pt, err := client.NewPoint( + db.ReadingsCollection, + tags, + fields, + time.Now(), + ) + if err != nil { + return err + } + bp.AddPoint(pt) + } + stringArray = append(stringArray, e.Readings[i].Id.Hex()) + } + readings := strings.Join(stringArray, " ") + + fields := map[string]interface{}{ + "pushed": e.Pushed, + "created": e.Created, + "origin": e.Origin, + "modified": e.Modified, + "readings": readings, + } + + tags := map[string]string{ + "id": e.ID.Hex(), + "device": e.Device, + "event": e.Event, + } + + pt, err := client.NewPoint( + collection, + tags, + fields, + time.Now(), + ) + if err != nil { + return err + } + bp.AddPoint(pt) + return ic.Client.Write(bp) +} + +func parseEvents(res client.Result) ([]models.Event, error) { + var events []models.Event + for i, _ := range res.Series[0].Values { + var event models.Event + var readings []string + for j, col := range res.Series[0].Columns { + switch col { + case "id": + event.ID = bson.ObjectIdHex(res.Series[0].Values[i][j].(string)) + case "pushed": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return events, err + } + event.Pushed = n + case "created": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return events, err + } + event.Created = n + case "origin": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return events, err + } + event.Origin = n + case "modified": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return events, err + } + event.Modified = n + case "device": + if res.Series[0].Values[i][j] != nil { + event.Device = res.Series[0].Values[i][j].(string) + } + case "event": + if res.Series[0].Values[i][j] != nil { + event.Event = res.Series[0].Values[i][j].(string) + } + case "readings": + if res.Series[0].Values[i][j] != nil { + s := res.Series[0].Values[i][j].(string) + readings = strings.Split(s, " ") + } + } + } + for _, id := range readings { + reading, err := currentInfluxClient.ReadingById(id) + if err != nil { + return events, nil + } + event.Readings = append(event.Readings, reading) + } + + events = append(events, event) + } + return events, nil +} + +// ************************ READINGS ************************************ + +// Return a list of readings sorted by reading id +func (ic *InfluxClient) Readings() ([]models.Reading, error) { + return ic.getReadings("") +} + +// Post a new reading +func (ic *InfluxClient) AddReading(r models.Reading) (bson.ObjectId, error) { + // Get the reading ready + r.Id = bson.NewObjectId() + r.Created = time.Now().UnixNano() / int64(time.Millisecond) + err := ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) + return r.Id, err +} + +// Update a reading +// 404 - reading cannot be found +// 409 - Value descriptor doesn't exist +// 503 - unknown issues +func (ic *InfluxClient) UpdateReading(r models.Reading) error { + r.Modified = time.Now().UnixNano() / int64(time.Millisecond) + + // Delete reading + if err := ic.deleteById(db.ReadingsCollection, r.Id.Hex()); err != nil { + return err + } + + // Add the reading + return ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) +} + +// Get a reading by ID +func (ic *InfluxClient) ReadingById(id string) (models.Reading, error) { + // Check if the id is a id hex + if !bson.IsObjectIdHex(id) { + return models.Reading{}, db.ErrInvalidObjectId + } + + query := fmt.Sprintf("WHERE id = '%s'", id) + readings, err := ic.getReadings(query) + return readings[0], err +} + +// Get the count of readings in Influx +func (ic *InfluxClient) ReadingCount() (int, error) { + query := fmt.Sprintf("SELECT COUNT(*) FROM %s", db.ReadingsCollection) + return ic.getCount(query) +} + +// Delete a reading by ID +// 404 - can't find the reading with the given id +func (ic *InfluxClient) DeleteReadingById(id string) error { + return ic.deleteById(db.ReadingsCollection, id) +} + +// Return a list of readings for the given device (id or name) +// Sort the list of readings on creation date +func (ic *InfluxClient) ReadingsByDevice(id string, limit int) ([]models.Reading, error) { + query := fmt.Sprintf("WHERE device = '%s' LIMIT %d", id, limit) + return ic.getReadings(query) +} + +// Return a list of readings for the given value descriptor +// Limit by the given limit +func (ic *InfluxClient) ReadingsByValueDescriptor(name string, limit int) ([]models.Reading, error) { + query := fmt.Sprintf("WHERE name = '%s' LIMIT %d", name, limit) + return ic.getReadings(query) +} + +// Return a list of readings whose name is in the list of value descriptor names +func (ic *InfluxClient) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { + var readings []models.Reading + for _, name := range names { + query := fmt.Sprintf("WHERE name = '%s' LIMIT %d", name, limit) + rlist, err := ic.getReadings(query) + if err != nil { + return readings, err + } + readings = append(readings, rlist...) + } + return readings, nil +} + +// Return a list of readings whos creation time is in-between start and end +// Limit by the limit parameter +func (ic *InfluxClient) ReadingsByCreationTime(start, end int64, limit int) ([]models.Reading, error) { + query := fmt.Sprintf("WHERE created >= %d AND created <= %d LIMIT %d", start, end, limit) + return ic.getReadings(query) +} + +// Return a list of readings for a device filtered by the value descriptor and limited by the limit +// The readings are linked to the device through an event +func (ic *InfluxClient) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor string, limit int) ([]models.Reading, error) { + query := fmt.Sprintf("WHERE device = '%s' AND value = '%s' LIMIT %d", deviceId, valueDescriptor, limit) + return ic.getReadings(query) +} + +// Get readings for the passed query +func (ic *InfluxClient) getReadings(q string) ([]models.Reading, error) { + readings := []models.Reading{} + query := fmt.Sprintf("SELECT * FROM %s %s", db.ReadingsCollection, q) + res, err := ic.queryDB(query) + if err != nil { + return readings, err + } + + if len(res) == 1 { + if len(res[0].Series) == 1 { + readings, err = parseReadings(res[0]) + if err != nil { + return readings, err + } + } + } + + return readings, nil +} + +func (ic *InfluxClient) addReadingToDB(db string, collection string, r *models.Reading) error { + bp, err := client.NewBatchPoints(client.BatchPointsConfig{ + Database: db, + Precision: "us", + }) + if err != nil { + return err + } + fields := map[string]interface{}{ + "pushed": r.Pushed, + "created": r.Created, + "origin": r.Origin, + "modified": r.Modified, + } + + tags := map[string]string{ + "id": r.Id.Hex(), + "device": r.Device, + "name": r.Name, + "value": r.Value, + } + + pt, err := client.NewPoint( + collection, + tags, + fields, + time.Now(), + ) + if err != nil { + return err + } + bp.AddPoint(pt) + return ic.Client.Write(bp) +} + +func parseReadings(res client.Result) ([]models.Reading, error) { + var readings []models.Reading + for i, _ := range res.Series[0].Values { + var reading models.Reading + for j, col := range res.Series[0].Columns { + switch col { + case "id": + reading.Id = bson.ObjectIdHex(res.Series[0].Values[i][j].(string)) + case "pushed": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return readings, err + } + reading.Pushed = n + case "created": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return readings, err + } + reading.Created = n + case "origin": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return readings, err + } + reading.Origin = n + case "modified": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return readings, err + } + reading.Modified = n + case "device": + if res.Series[0].Values[i][j] != nil { + reading.Device = res.Series[0].Values[i][j].(string) + } + case "name": + if res.Series[0].Values[i][j] != nil { + reading.Name = res.Series[0].Values[i][j].(string) + } + case "value": + if res.Series[0].Values[i][j] != nil { + reading.Value = res.Series[0].Values[i][j].(string) + } + } + } + + readings = append(readings, reading) + } + return readings, nil +} + +// ************************* VALUE DESCRIPTORS ***************************** + +// Add a value descriptor +// 409 - Formatting is bad or it is not unique +// 503 - Unexpected +// TODO: Check for valid printf formatting +func (ic *InfluxClient) AddValueDescriptor(v models.ValueDescriptor) (bson.ObjectId, error) { + // Created/Modified now + v.Created = time.Now().UnixNano() / int64(time.Millisecond) + + // See if the name is unique and add the value descriptors + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE 'name' = '%s'", db.ValueDescriptorCollection, v.Name) + num, err := ic.getCount(query) + if err != nil { + return v.Id, err + } + + // Duplicate name + if num != 0 { + return v.Id, db.ErrNotUnique + } + + // Set id + v.Id = bson.NewObjectId() + + // Add Value Descriptor + err = ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) + if err != nil { + return v.Id, err + } + + return v.Id, err +} + +// Return a list of all the value descriptors +// 513 Service Unavailable - database problems +func (ic *InfluxClient) ValueDescriptors() ([]models.ValueDescriptor, error) { + return ic.getValueDescriptors("") +} + +// Update a value descriptor +// First use the ID for identification, then the name +// TODO: Check for the valid printf formatting +// 404 not found if the value descriptor cannot be found by the identifiers +func (ic *InfluxClient) UpdateValueDescriptor(v models.ValueDescriptor) error { + // See if the name is unique if it changed + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE id = '%s'", db.ValueDescriptorCollection, v.Id) + num, err := ic.getCount(query) + if err != nil { + return err + } + if num != 0 { + return db.ErrNotUnique + } + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE name = '%s'", db.ValueDescriptorCollection, v.Name) + num, err = ic.getCount(query) + if err != nil { + return err + } + if num != 0 { + query = fmt.Sprintf("WHERE name = '%s'", v.Name) + err := ic.deleteValueDescriptorBy(query) + if err != nil { + return err + } + } + v.Modified = time.Now().UnixNano() / int64(time.Millisecond) + // Delete Value Descriptor + // Add Value Descriptor + return ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) +} + +// Delete the value descriptor based on the id +// Not found error if there isn't a value descriptor for the ID +// ValueDescriptorStillInUse if the value descriptor is still referenced by readings +func (ic *InfluxClient) DeleteValueDescriptorById(id string) error { + query := fmt.Sprintf("WHERE id = '%s'", id) + return ic.deleteValueDescriptorBy(query) +} + +// Return a value descriptor based on the name +// Can return null if no value descriptor is found +func (ic *InfluxClient) ValueDescriptorByName(name string) (models.ValueDescriptor, error) { + query := fmt.Sprintf("WHERE \"name\" = '%s'", name) + v, err := ic.getValueDescriptors(query) + if err != nil || len(v) < 1 { + var vret models.ValueDescriptor + return vret, err + } + return v[0], err +} + +// Return all of the value descriptors based on the names +func (ic *InfluxClient) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor, error) { + vList := []models.ValueDescriptor{} + + for _, name := range names { + query := fmt.Sprintf("WHERE name = '%s'", name) + v, err := ic.getValueDescriptors(query) + if err != nil || len(v) < 1 { + return []models.ValueDescriptor{}, err + } + vList = append(vList, v[0]) + } + + return vList, nil +} + +// Return a value descriptor based on the id +// Return NotFoundError if there is no value descriptor for the id +func (ic *InfluxClient) ValueDescriptorById(id string) (models.ValueDescriptor, error) { + if !bson.IsObjectIdHex(id) { + return models.ValueDescriptor{}, db.ErrInvalidObjectId + } + + query := fmt.Sprintf("WHERE id = '%s'", id) + v, err := ic.getValueDescriptors(query) + if err != nil || len(v) < 1 { + return models.ValueDescriptor{}, err + } + return v[0], err +} + +// Return all the value descriptors that match the UOM label +func (ic *InfluxClient) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescriptor, error) { + query := fmt.Sprintf("WHERE uomLabel = '%s'", uomLabel) + return ic.getValueDescriptors(query) +} + +// Return value descriptors based on if it has the label +func (ic *InfluxClient) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, error) { + query := fmt.Sprintf("WHERE label = '%s'", label) + return ic.getValueDescriptors(query) +} + +// Return value descriptors based on if it has the label +func (ic *InfluxClient) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, error) { + query := fmt.Sprintf("WHERE type = '%s'", t) + return ic.getValueDescriptors(query) +} + +// Delete all of the value descriptors +func (ic *InfluxClient) ScrubAllValueDescriptors() error { + return ic.deleteAll(db.ValueDescriptorCollection) +} + +func (ic *InfluxClient) deleteValueDescriptorBy(query string) error { + q := fmt.Sprintf("DELETE FROM %s %s", db.ValueDescriptorCollection, query) + _, err := ic.queryDB(q) + if err != nil { + return err + } + return nil +} + +// Get value descriptors for the passed query +func (ic *InfluxClient) getValueDescriptors(q string) ([]models.ValueDescriptor, error) { + vds := []models.ValueDescriptor{} + query := fmt.Sprintf("SELECT * FROM %s %s", db.ValueDescriptorCollection, q) + res, err := ic.queryDB(query) + if err != nil { + return vds, err + } + + if len(res) == 1 { + if len(res[0].Series) == 1 { + vds, err = parseValueDescriptors(res[0]) + if err != nil { + return vds, err + } + } + } + + return vds, nil +} + +func (ic *InfluxClient) addValueDescriptorToDB(db string, collection string, v *models.ValueDescriptor) error { + bp, err := client.NewBatchPoints(client.BatchPointsConfig{ + Database: db, + Precision: "us", + }) + if err != nil { + return err + } + fields := map[string]interface{}{ + "description": v.Description, + "created": v.Created, + "origin": v.Origin, + "modified": v.Modified, + "min": v.Min, + "max": v.Max, + "defaultvalue": v.DefaultValue, + "Labels": v.Labels, + } + + tags := map[string]string{ + "id": v.Id.Hex(), + "name": v.Name, + "UomLabel": v.UomLabel, + "type": v.Type, + "formatting": v.Formatting, + } + + pt, err := client.NewPoint( + collection, + tags, + fields, + time.Now(), + ) + if err != nil { + return err + } + bp.AddPoint(pt) + return ic.Client.Write(bp) +} + +func parseValueDescriptors(res client.Result) ([]models.ValueDescriptor, error) { + var vds []models.ValueDescriptor + for i, _ := range res.Series[0].Values { + var vd models.ValueDescriptor + for j, col := range res.Series[0].Columns { + switch col { + case "id": + vd.Id = bson.ObjectIdHex(res.Series[0].Values[i][j].(string)) + case "created": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return vds, err + } + vd.Created = n + case "origin": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return vds, err + } + vd.Origin = n + case "modified": + n, err := res.Series[0].Values[i][j].(json.Number).Int64() + if err != nil { + return vds, err + } + vd.Modified = n + case "name": + if res.Series[0].Values[i][j] != nil { + vd.Name = res.Series[0].Values[i][j].(string) + } + case "description": + if res.Series[0].Values[i][j] != nil { + vd.Description = res.Series[0].Values[i][j].(string) + } + case "min": + if res.Series[0].Values[i][j] != nil { + vd.Min = res.Series[0].Values[i][j].(string) + } + case "max": + if res.Series[0].Values[i][j] != nil { + vd.Max = res.Series[0].Values[i][j].(string) + } + case "type": + if res.Series[0].Values[i][j] != nil { + vd.Type = res.Series[0].Values[i][j].(string) + } + case "uomLabel": + if res.Series[0].Values[i][j] != nil { + vd.UomLabel = res.Series[0].Values[i][j].(string) + } + case "labels": + // ToDo set labels + strings := []string{"dummy"} + vd.Labels = strings + case "defalutvalue": + if res.Series[0].Values[i][j] != nil { + vd.DefaultValue = res.Series[0].Values[i][j].(string) + } + } + } + + vds = append(vds, vd) + } + return vds, nil +} diff --git a/core/db/memory/client.go b/core/db/memory/client.go new file mode 100644 index 0000000000..78848d4d11 --- /dev/null +++ b/core/db/memory/client.go @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright 2018 Cavium + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ +package memory + +import "github.com/edgexfoundry/edgex-go/core/domain/models" + +type MemDB struct { + // Data + readings []models.Reading + events []models.Event + vDescriptors []models.ValueDescriptor + + // Metadata + addressables []models.Addressable + commands []models.Command + deviceServices []models.DeviceService + schedules []models.Schedule + scheduleEvents []models.ScheduleEvent + provisionWatchers []models.ProvisionWatcher + deviceReports []models.DeviceReport + deviceProfiles []models.DeviceProfile + devices []models.Device +} + +func (m *MemDB) CloseSession() { +} + +func (m *MemDB) Connect() error { + return nil +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/core/db/memory/data.go b/core/db/memory/data.go index 39ed165602..64cca910ec 100644 --- a/core/db/memory/data.go +++ b/core/db/memory/data.go @@ -21,31 +21,6 @@ import ( "gopkg.in/mgo.v2/bson" ) -type MemDB struct { - // Data - readings []models.Reading - events []models.Event - vDescriptors []models.ValueDescriptor - - // Metadata - addressables []models.Addressable - commands []models.Command - deviceServices []models.DeviceService - schedules []models.Schedule - scheduleEvents []models.ScheduleEvent - provisionWatchers []models.ProvisionWatcher - deviceReports []models.DeviceReport - deviceProfiles []models.DeviceProfile - devices []models.Device -} - -func (m *MemDB) CloseSession() { -} - -func (m *MemDB) Connect() error { - return nil -} - func (m *MemDB) AddReading(r models.Reading) (bson.ObjectId, error) { currentTime := time.Now().UnixNano() / int64(time.Millisecond) r.Created = currentTime @@ -273,15 +248,6 @@ func (m *MemDB) ReadingsByValueDescriptor(name string, limit int) ([]models.Read return readings, nil } -func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } - } - return false -} - func (m *MemDB) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { readings := []models.Reading{} count := 0 diff --git a/core/db/mongo/client.go b/core/db/mongo/client.go index 8cfe982f27..7b5af98332 100644 --- a/core/db/mongo/client.go +++ b/core/db/mongo/client.go @@ -15,28 +15,16 @@ package mongo import ( "errors" + "strconv" "time" "github.com/edgexfoundry/edgex-go/core/db" - "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) var currentMongoClient *MongoClient // Singleton used so that mongoEvent can use it to de-reference readings -/* -Core data client -Has functions for interacting with the core data mongo database -*/ - -// Type used to sort the readings by creation date -type ByReadingCreationDate []models.Reading - -func (a ByReadingCreationDate) Len() int { return len(a) } -func (a ByReadingCreationDate) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a ByReadingCreationDate) Less(i, j int) bool { return (a[i].Created < a[j].Created) } - type MongoClient struct { config db.Configuration session *mgo.Session // Mongo database session @@ -50,551 +38,47 @@ func NewClient(config db.Configuration) *MongoClient { return mongoClient } -// Get the current Mongo Client -func getCurrentMongoClient() (*MongoClient, error) { - if currentMongoClient == nil { - return nil, errors.New("No current mongo client, please create a new client before requesting it") - } - - return currentMongoClient, nil -} - -// Get a copy of the session -func (mc *MongoClient) getSessionCopy() *mgo.Session { - return mc.session.Copy() -} - -// ******************************* EVENTS ********************************** - -// Return all the events -// UnexpectedError - failed to retrieve events from the database -// Sort the events in descending order by ID -func (mc *MongoClient) Events() ([]models.Event, error) { - return mc.getEvents(bson.M{}) -} - -// Add a new event -// UnexpectedError - failed to add to database -// NoValueDescriptor - no existing value descriptor for a reading in the event -func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { - s := mc.getSessionCopy() - defer s.Close() - - e.Created = time.Now().UnixNano() / int64(time.Millisecond) - e.ID = bson.NewObjectId() - - // Insert readings - var ui []interface{} - if len(e.Readings) != 0 { - for i := range e.Readings { - e.Readings[i].Id = bson.NewObjectId() - e.Readings[i].Created = e.Created - e.Readings[i].Device = e.Device - ui = append(ui, e.Readings[i]) - } - err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(ui...) - if err != nil { - return e.ID, err - } +func (m *MongoClient) Connect() error { + // Create the dial info for the Mongo session + connectionString := m.config.Host + ":" + strconv.Itoa(m.config.Port) + mongoDBDialInfo := &mgo.DialInfo{ + Addrs: []string{connectionString}, + Timeout: time.Duration(m.config.Timeout) * time.Millisecond, + Database: m.config.DatabaseName, + Username: m.config.Username, + Password: m.config.Password, } - - // Handle DBRefs - me := mongoEvent{Event: *e} - - // Add the event - err := s.DB(mc.database.Name).C(db.EventsCollection).Insert(me) - if err != nil { - return e.ID, err - } - - return e.ID, err -} - -// Update an event - do NOT update readings -// UnexpectedError - problem updating in database -// NotFound - no event with the ID was found -func (mc *MongoClient) UpdateEvent(e models.Event) error { - s := mc.getSessionCopy() - defer s.Close() - - e.Modified = time.Now().UnixNano() / int64(time.Millisecond) - - // Handle DBRef - me := mongoEvent{Event: e} - - err := s.DB(mc.database.Name).C(db.EventsCollection).UpdateId(me.ID, me) - if err == mgo.ErrNotFound { - return db.ErrNotFound - } - - return err -} - -// Get an event by id -func (mc *MongoClient) EventById(id string) (models.Event, error) { - if !bson.IsObjectIdHex(id) { - return models.Event{}, db.ErrInvalidObjectId - } - return mc.getEvent(bson.M{"_id": bson.ObjectIdHex(id)}) -} - -// Get the number of events in Mongo -func (mc *MongoClient) EventCount() (int, error) { - s := mc.getSessionCopy() - defer s.Close() - - return s.DB(mc.database.Name).C(db.EventsCollection).Find(nil).Count() -} - -// Get the number of events in Mongo for the device -func (mc *MongoClient) EventCountByDeviceId(id string) (int, error) { - s := mc.getSessionCopy() - defer s.Close() - - query := bson.M{"device": id} - return s.DB(mc.database.Name).C(db.EventsCollection).Find(query).Count() -} - -// Delete an event by ID and all of its readings -// 404 - Event not found -// 503 - Unexpected problems -func (mc *MongoClient) DeleteEventById(id string) error { - return mc.deleteById(db.EventsCollection, id) -} - -// Get a list of events based on the device id and limit -func (mc *MongoClient) EventsForDeviceLimit(id string, limit int) ([]models.Event, error) { - return mc.getEventsLimit(bson.M{"device": id}, limit) -} - -// Get a list of events based on the device id -func (mc *MongoClient) EventsForDevice(id string) ([]models.Event, error) { - return mc.getEvents(bson.M{"device": id}) -} - -// Return a list of events whos creation time is between startTime and endTime -// Limit the number of results by limit -func (mc *MongoClient) EventsByCreationTime(startTime, endTime int64, limit int) ([]models.Event, error) { - query := bson.M{"created": bson.M{ - "$gte": startTime, - "$lte": endTime, - }} - return mc.getEventsLimit(query, limit) -} - -// Get Events that are older than the given age (defined by age = now - created) -func (mc *MongoClient) EventsOlderThanAge(age int64) ([]models.Event, error) { - expireDate := (time.Now().UnixNano() / int64(time.Millisecond)) - age - return mc.getEvents(bson.M{"created": bson.M{"$lt": expireDate}}) -} - -// Get all of the events that have been pushed -func (mc *MongoClient) EventsPushed() ([]models.Event, error) { - return mc.getEvents(bson.M{"pushed": bson.M{"$gt": int64(0)}}) -} - -// Delete all of the readings and all of the events -func (mc *MongoClient) ScrubAllEvents() error { - s := mc.getSessionCopy() - defer s.Close() - - _, err := s.DB(mc.database.Name).C(db.ReadingsCollection).RemoveAll(nil) + session, err := mgo.DialWithInfo(mongoDBDialInfo) if err != nil { return err } - _, err = s.DB(mc.database.Name).C(db.EventsCollection).RemoveAll(nil) - if err != nil { - return err - } + m.session = session + m.database = session.DB(m.config.DatabaseName) + currentMongoClient = m // Set the singleton return nil } -// Get events for the passed query -func (mc *MongoClient) getEvents(q bson.M) ([]models.Event, error) { - s := mc.getSessionCopy() - defer s.Close() - - // Handle DBRefs - var me []mongoEvent - events := []models.Event{} - err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).All(&me) - if err != nil { - return events, err - } - - // Append all the events - for _, e := range me { - events = append(events, e.Event) - } - - return events, nil -} - -// Get events with a limit -func (mc *MongoClient) getEventsLimit(q bson.M, limit int) ([]models.Event, error) { - s := mc.getSessionCopy() - defer s.Close() - - // Handle DBRefs - var me []mongoEvent - events := []models.Event{} - - // Check if limit is 0 - if limit == 0 { - return events, nil - } - - err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).Limit(limit).All(&me) - if err != nil { - return events, err +func (m *MongoClient) CloseSession() { + if m.session != nil { + m.session.Close() + m.session = nil } - - // Append all the events - for _, e := range me { - events = append(events, e.Event) - } - - return events, nil } -// Get a single event for the passed query -func (mc *MongoClient) getEvent(q bson.M) (models.Event, error) { - s := mc.getSessionCopy() - defer s.Close() - - // Handle DBRef - var me mongoEvent - err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).One(&me) - if err == mgo.ErrNotFound { - return me.Event, db.ErrNotFound - } - - return me.Event, err -} - -// ************************ READINGS ************************************8 - -// Return a list of readings sorted by reading id -func (mc *MongoClient) Readings() ([]models.Reading, error) { - return mc.getReadings(nil) -} - -// Post a new reading -func (mc *MongoClient) AddReading(r models.Reading) (bson.ObjectId, error) { - s := mc.getSessionCopy() - defer s.Close() - - // Get the reading ready - r.Id = bson.NewObjectId() - r.Created = time.Now().UnixNano() / int64(time.Millisecond) - - err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(&r) - return r.Id, err -} - -// Update a reading -// 404 - reading cannot be found -// 409 - Value descriptor doesn't exist -// 503 - unknown issues -func (mc *MongoClient) UpdateReading(r models.Reading) error { - s := mc.getSessionCopy() - defer s.Close() - - r.Modified = time.Now().UnixNano() / int64(time.Millisecond) - - // Update the reading - err := s.DB(mc.database.Name).C(db.ReadingsCollection).UpdateId(r.Id, r) - if err == mgo.ErrNotFound { - return db.ErrNotFound - } - - return err -} - -// Get a reading by ID -func (mc *MongoClient) ReadingById(id string) (models.Reading, error) { - // Check if the id is a id hex - if !bson.IsObjectIdHex(id) { - return models.Reading{}, db.ErrInvalidObjectId - } - - query := bson.M{"_id": bson.ObjectIdHex(id)} - - return mc.getReading(query) -} - -// Get the count of readings in Mongo -func (mc *MongoClient) ReadingCount() (int, error) { - s := mc.getSessionCopy() - defer s.Close() - - return s.DB(mc.database.Name).C(db.ReadingsCollection).Find(bson.M{}).Count() -} - -// Delete a reading by ID -// 404 - can't find the reading with the given id -func (mc *MongoClient) DeleteReadingById(id string) error { - // Check if the id is a bson id - if !bson.IsObjectIdHex(id) { - return db.ErrInvalidObjectId - } - - return mc.deleteById(db.ReadingsCollection, id) -} - -// Return a list of readings for the given device (id or name) -// Sort the list of readings on creation date -func (mc *MongoClient) ReadingsByDevice(id string, limit int) ([]models.Reading, error) { - query := bson.M{"device": id} - return mc.getReadingsLimit(query, limit) -} - -// Return a list of readings for the given value descriptor -// Limit by the given limit -func (mc *MongoClient) ReadingsByValueDescriptor(name string, limit int) ([]models.Reading, error) { - query := bson.M{"name": name} - return mc.getReadingsLimit(query, limit) -} - -// Return a list of readings whose name is in the list of value descriptor names -func (mc *MongoClient) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { - query := bson.M{"name": bson.M{"$in": names}} - return mc.getReadingsLimit(query, limit) -} - -// Return a list of readings whos creation time is in-between start and end -// Limit by the limit parameter -func (mc *MongoClient) ReadingsByCreationTime(start, end int64, limit int) ([]models.Reading, error) { - query := bson.M{"created": bson.M{ - "$gte": start, - "$lte": end, - }} - return mc.getReadingsLimit(query, limit) -} - -// Return a list of readings for a device filtered by the value descriptor and limited by the limit -// The readings are linked to the device through an event -func (mc *MongoClient) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor string, limit int) ([]models.Reading, error) { - query := bson.M{"device": deviceId, "name": valueDescriptor} - return mc.getReadingsLimit(query, limit) -} - -func (mc *MongoClient) getReadingsLimit(q bson.M, limit int) ([]models.Reading, error) { - s := mc.getSessionCopy() - defer s.Close() - - readings := []models.Reading{} - - // Check if limit is 0 - if limit == 0 { - return readings, nil - } - - err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).Limit(limit).All(&readings) - return readings, err -} - -// Get readings from the database -func (mc *MongoClient) getReadings(q bson.M) ([]models.Reading, error) { - s := mc.getSessionCopy() - defer s.Close() - - readings := []models.Reading{} - err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).All(&readings) - return readings, err -} - -// Get a reading from the database with the passed query -func (mc *MongoClient) getReading(q bson.M) (models.Reading, error) { - s := mc.getSessionCopy() - defer s.Close() - - var res models.Reading - err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).One(&res) - if err == mgo.ErrNotFound { - return res, db.ErrNotFound - } - return res, err -} - -// ************************* VALUE DESCRIPTORS ***************************** - -// Add a value descriptor -// 409 - Formatting is bad or it is not unique -// 503 - Unexpected -// TODO: Check for valid printf formatting -func (mc *MongoClient) AddValueDescriptor(v models.ValueDescriptor) (bson.ObjectId, error) { - s := mc.getSessionCopy() - defer s.Close() - - // Created/Modified now - v.Created = time.Now().UnixNano() / int64(time.Millisecond) - - // See if the name is unique and add the value descriptors - info, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Upsert(bson.M{"name": v.Name}, v) - if err != nil { - return v.Id, err - } - - // Duplicate name - if info.UpsertedId == nil { - return v.Id, db.ErrNotUnique - } - - // Set ID - v.Id = info.UpsertedId.(bson.ObjectId) - - return v.Id, err -} - -// Return a list of all the value descriptors -// 513 Service Unavailable - database problems -func (mc *MongoClient) ValueDescriptors() ([]models.ValueDescriptor, error) { - return mc.getValueDescriptors(nil) -} - -// Update a value descriptor -// First use the ID for identification, then the name -// TODO: Check for the valid printf formatting -// 404 not found if the value descriptor cannot be found by the identifiers -func (mc *MongoClient) UpdateValueDescriptor(v models.ValueDescriptor) error { - s := mc.getSessionCopy() - defer s.Close() - - // See if the name is unique if it changed - vd, err := mc.getValueDescriptor(bson.M{"name": v.Name}) - if err != db.ErrNotFound { - if err != nil { - return err - } - - // IDs are different -> name not unique - if vd.Id != v.Id { - return db.ErrNotUnique - } - } - - v.Modified = time.Now().UnixNano() / int64(time.Millisecond) - - err = s.DB(mc.database.Name).C(db.ValueDescriptorCollection).UpdateId(v.Id, v) - if err == mgo.ErrNotFound { - return db.ErrNotFound - } - return err -} - -// Delete the value descriptor based on the id -// Not found error if there isn't a value descriptor for the ID -// ValueDescriptorStillInUse if the value descriptor is still referenced by readings -func (mc *MongoClient) DeleteValueDescriptorById(id string) error { - if !bson.IsObjectIdHex(id) { - return db.ErrInvalidObjectId - } - return mc.deleteById(db.ValueDescriptorCollection, id) -} - -// Return a value descriptor based on the name -// Can return null if no value descriptor is found -func (mc *MongoClient) ValueDescriptorByName(name string) (models.ValueDescriptor, error) { - query := bson.M{"name": name} - return mc.getValueDescriptor(query) -} - -// Return all of the value descriptors based on the names -func (mc *MongoClient) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor, error) { - vList := []models.ValueDescriptor{} - - for _, name := range names { - v, err := mc.ValueDescriptorByName(name) - if err != nil && err != db.ErrNotFound { - return []models.ValueDescriptor{}, err - } - if err == nil { - vList = append(vList, v) - } - } - - return vList, nil -} - -// Return a value descriptor based on the id -// Return NotFoundError if there is no value descriptor for the id -func (mc *MongoClient) ValueDescriptorById(id string) (models.ValueDescriptor, error) { - if !bson.IsObjectIdHex(id) { - return models.ValueDescriptor{}, db.ErrInvalidObjectId - } - - query := bson.M{"_id": bson.ObjectIdHex(id)} - return mc.getValueDescriptor(query) -} - -// Return all the value descriptors that match the UOM label -func (mc *MongoClient) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescriptor, error) { - query := bson.M{"uomLabel": uomLabel} - return mc.getValueDescriptors(query) -} - -// Return value descriptors based on if it has the label -func (mc *MongoClient) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, error) { - query := bson.M{"labels": label} - return mc.getValueDescriptors(query) -} - -// Return value descriptors based on the type -func (mc *MongoClient) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, error) { - query := bson.M{"type": t} - return mc.getValueDescriptors(query) -} - -// Delete all of the value descriptors -func (mc *MongoClient) ScrubAllValueDescriptors() error { - s := mc.getSessionCopy() - defer s.Close() - - _, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).RemoveAll(nil) - if err != nil { - return err +// Get the current Mongo Client +func getCurrentMongoClient() (*MongoClient, error) { + if currentMongoClient == nil { + return nil, errors.New("No current mongo client, please create a new client before requesting it") } - return nil -} - -// Get value descriptors based on the query -func (mc *MongoClient) getValueDescriptors(q bson.M) ([]models.ValueDescriptor, error) { - s := mc.getSessionCopy() - defer s.Close() - - v := []models.ValueDescriptor{} - err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).All(&v) - - return v, err -} - -// Get value descriptors with a limit based on the query -func (mc *MongoClient) getValueDescriptorsLimit(q bson.M, limit int) ([]models.ValueDescriptor, error) { - s := mc.getSessionCopy() - defer s.Close() - - v := []models.ValueDescriptor{} - err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).Limit(limit).All(&v) - - return v, err + return currentMongoClient, nil } -// Get a value descriptor based on the query -func (mc *MongoClient) getValueDescriptor(q bson.M) (models.ValueDescriptor, error) { - s := mc.getSessionCopy() - defer s.Close() - - var v models.ValueDescriptor - err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).One(&v) - if err == mgo.ErrNotFound { - return v, db.ErrNotFound - } - - return v, err +// Get a copy of the session +func (mc *MongoClient) getSessionCopy() *mgo.Session { + return mc.session.Copy() } // Delete from the collection based on ID diff --git a/core/db/mongo/data.go b/core/db/mongo/data.go new file mode 100644 index 0000000000..4d688a6778 --- /dev/null +++ b/core/db/mongo/data.go @@ -0,0 +1,561 @@ +/******************************************************************************* + * Copyright 2017 Dell Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ +package mongo + +import ( + "time" + + "github.com/edgexfoundry/edgex-go/core/db" + "github.com/edgexfoundry/edgex-go/core/domain/models" + mgo "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" +) + +/* +Core data client +Has functions for interacting with the core data mongo database +*/ + +// ******************************* EVENTS ********************************** + +// Return all the events +// UnexpectedError - failed to retrieve events from the database +// Sort the events in descending order by ID +func (mc *MongoClient) Events() ([]models.Event, error) { + return mc.getEvents(bson.M{}) +} + +// Add a new event +// UnexpectedError - failed to add to database +// NoValueDescriptor - no existing value descriptor for a reading in the event +func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { + s := mc.getSessionCopy() + defer s.Close() + + e.Created = time.Now().UnixNano() / int64(time.Millisecond) + e.ID = bson.NewObjectId() + + // Insert readings + var ui []interface{} + if len(e.Readings) != 0 { + for i := range e.Readings { + e.Readings[i].Id = bson.NewObjectId() + e.Readings[i].Created = e.Created + e.Readings[i].Device = e.Device + ui = append(ui, e.Readings[i]) + } + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(ui...) + if err != nil { + return e.ID, err + } + } + + // Handle DBRefs + me := mongoEvent{Event: *e} + + // Add the event + err := s.DB(mc.database.Name).C(db.EventsCollection).Insert(me) + if err != nil { + return e.ID, err + } + + return e.ID, err +} + +// Update an event - do NOT update readings +// UnexpectedError - problem updating in database +// NotFound - no event with the ID was found +func (mc *MongoClient) UpdateEvent(e models.Event) error { + s := mc.getSessionCopy() + defer s.Close() + + e.Modified = time.Now().UnixNano() / int64(time.Millisecond) + + // Handle DBRef + me := mongoEvent{Event: e} + + err := s.DB(mc.database.Name).C(db.EventsCollection).UpdateId(me.ID, me) + if err == mgo.ErrNotFound { + return db.ErrNotFound + } + + return err +} + +// Get an event by id +func (mc *MongoClient) EventById(id string) (models.Event, error) { + if !bson.IsObjectIdHex(id) { + return models.Event{}, db.ErrInvalidObjectId + } + return mc.getEvent(bson.M{"_id": bson.ObjectIdHex(id)}) +} + +// Get the number of events in Mongo +func (mc *MongoClient) EventCount() (int, error) { + s := mc.getSessionCopy() + defer s.Close() + + return s.DB(mc.database.Name).C(db.EventsCollection).Find(nil).Count() +} + +// Get the number of events in Mongo for the device +func (mc *MongoClient) EventCountByDeviceId(id string) (int, error) { + s := mc.getSessionCopy() + defer s.Close() + + query := bson.M{"device": id} + return s.DB(mc.database.Name).C(db.EventsCollection).Find(query).Count() +} + +// Delete an event by ID and all of its readings +// 404 - Event not found +// 503 - Unexpected problems +func (mc *MongoClient) DeleteEventById(id string) error { + return mc.deleteById(db.EventsCollection, id) +} + +// Get a list of events based on the device id and limit +func (mc *MongoClient) EventsForDeviceLimit(id string, limit int) ([]models.Event, error) { + return mc.getEventsLimit(bson.M{"device": id}, limit) +} + +// Get a list of events based on the device id +func (mc *MongoClient) EventsForDevice(id string) ([]models.Event, error) { + return mc.getEvents(bson.M{"device": id}) +} + +// Return a list of events whos creation time is between startTime and endTime +// Limit the number of results by limit +func (mc *MongoClient) EventsByCreationTime(startTime, endTime int64, limit int) ([]models.Event, error) { + query := bson.M{"created": bson.M{ + "$gte": startTime, + "$lte": endTime, + }} + return mc.getEventsLimit(query, limit) +} + +// Get Events that are older than the given age (defined by age = now - created) +func (mc *MongoClient) EventsOlderThanAge(age int64) ([]models.Event, error) { + expireDate := (time.Now().UnixNano() / int64(time.Millisecond)) - age + return mc.getEvents(bson.M{"created": bson.M{"$lt": expireDate}}) +} + +// Get all of the events that have been pushed +func (mc *MongoClient) EventsPushed() ([]models.Event, error) { + return mc.getEvents(bson.M{"pushed": bson.M{"$gt": int64(0)}}) +} + +// Delete all of the readings and all of the events +func (mc *MongoClient) ScrubAllEvents() error { + s := mc.getSessionCopy() + defer s.Close() + + _, err := s.DB(mc.database.Name).C(db.ReadingsCollection).RemoveAll(nil) + if err != nil { + return err + } + + _, err = s.DB(mc.database.Name).C(db.EventsCollection).RemoveAll(nil) + if err != nil { + return err + } + + return nil +} + +// Get events for the passed query +func (mc *MongoClient) getEvents(q bson.M) ([]models.Event, error) { + s := mc.getSessionCopy() + defer s.Close() + + // Handle DBRefs + var me []mongoEvent + events := []models.Event{} + err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).All(&me) + if err != nil { + return events, err + } + + // Append all the events + for _, e := range me { + events = append(events, e.Event) + } + + return events, nil +} + +// Get events with a limit +func (mc *MongoClient) getEventsLimit(q bson.M, limit int) ([]models.Event, error) { + s := mc.getSessionCopy() + defer s.Close() + + // Handle DBRefs + var me []mongoEvent + events := []models.Event{} + + // Check if limit is 0 + if limit == 0 { + return events, nil + } + + err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).Limit(limit).All(&me) + if err != nil { + return events, err + } + + // Append all the events + for _, e := range me { + events = append(events, e.Event) + } + + return events, nil +} + +// Get a single event for the passed query +func (mc *MongoClient) getEvent(q bson.M) (models.Event, error) { + s := mc.getSessionCopy() + defer s.Close() + + // Handle DBRef + var me mongoEvent + err := s.DB(mc.database.Name).C(db.EventsCollection).Find(q).One(&me) + if err == mgo.ErrNotFound { + return me.Event, db.ErrNotFound + } + + return me.Event, err +} + +// ************************ READINGS ************************************8 + +// Return a list of readings sorted by reading id +func (mc *MongoClient) Readings() ([]models.Reading, error) { + return mc.getReadings(nil) +} + +// Post a new reading +func (mc *MongoClient) AddReading(r models.Reading) (bson.ObjectId, error) { + s := mc.getSessionCopy() + defer s.Close() + + // Get the reading ready + r.Id = bson.NewObjectId() + r.Created = time.Now().UnixNano() / int64(time.Millisecond) + + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(&r) + return r.Id, err +} + +// Update a reading +// 404 - reading cannot be found +// 409 - Value descriptor doesn't exist +// 503 - unknown issues +func (mc *MongoClient) UpdateReading(r models.Reading) error { + s := mc.getSessionCopy() + defer s.Close() + + r.Modified = time.Now().UnixNano() / int64(time.Millisecond) + + // Update the reading + err := s.DB(mc.database.Name).C(db.ReadingsCollection).UpdateId(r.Id, r) + if err == mgo.ErrNotFound { + return db.ErrNotFound + } + + return err +} + +// Get a reading by ID +func (mc *MongoClient) ReadingById(id string) (models.Reading, error) { + // Check if the id is a id hex + if !bson.IsObjectIdHex(id) { + return models.Reading{}, db.ErrInvalidObjectId + } + + query := bson.M{"_id": bson.ObjectIdHex(id)} + + return mc.getReading(query) +} + +// Get the count of readings in Mongo +func (mc *MongoClient) ReadingCount() (int, error) { + s := mc.getSessionCopy() + defer s.Close() + + return s.DB(mc.database.Name).C(db.ReadingsCollection).Find(bson.M{}).Count() +} + +// Delete a reading by ID +// 404 - can't find the reading with the given id +func (mc *MongoClient) DeleteReadingById(id string) error { + // Check if the id is a bson id + if !bson.IsObjectIdHex(id) { + return db.ErrInvalidObjectId + } + + return mc.deleteById(db.ReadingsCollection, id) +} + +// Return a list of readings for the given device (id or name) +// Sort the list of readings on creation date +func (mc *MongoClient) ReadingsByDevice(id string, limit int) ([]models.Reading, error) { + query := bson.M{"device": id} + return mc.getReadingsLimit(query, limit) +} + +// Return a list of readings for the given value descriptor +// Limit by the given limit +func (mc *MongoClient) ReadingsByValueDescriptor(name string, limit int) ([]models.Reading, error) { + query := bson.M{"name": name} + return mc.getReadingsLimit(query, limit) +} + +// Return a list of readings whose name is in the list of value descriptor names +func (mc *MongoClient) ReadingsByValueDescriptorNames(names []string, limit int) ([]models.Reading, error) { + query := bson.M{"name": bson.M{"$in": names}} + return mc.getReadingsLimit(query, limit) +} + +// Return a list of readings whos creation time is in-between start and end +// Limit by the limit parameter +func (mc *MongoClient) ReadingsByCreationTime(start, end int64, limit int) ([]models.Reading, error) { + query := bson.M{"created": bson.M{ + "$gte": start, + "$lte": end, + }} + return mc.getReadingsLimit(query, limit) +} + +// Return a list of readings for a device filtered by the value descriptor and limited by the limit +// The readings are linked to the device through an event +func (mc *MongoClient) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor string, limit int) ([]models.Reading, error) { + query := bson.M{"device": deviceId, "name": valueDescriptor} + return mc.getReadingsLimit(query, limit) +} + +func (mc *MongoClient) getReadingsLimit(q bson.M, limit int) ([]models.Reading, error) { + s := mc.getSessionCopy() + defer s.Close() + + readings := []models.Reading{} + + // Check if limit is 0 + if limit == 0 { + return readings, nil + } + + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).Limit(limit).All(&readings) + return readings, err +} + +// Get readings from the database +func (mc *MongoClient) getReadings(q bson.M) ([]models.Reading, error) { + s := mc.getSessionCopy() + defer s.Close() + + readings := []models.Reading{} + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).All(&readings) + return readings, err +} + +// Get a reading from the database with the passed query +func (mc *MongoClient) getReading(q bson.M) (models.Reading, error) { + s := mc.getSessionCopy() + defer s.Close() + + var res models.Reading + err := s.DB(mc.database.Name).C(db.ReadingsCollection).Find(q).One(&res) + if err == mgo.ErrNotFound { + return res, db.ErrNotFound + } + return res, err +} + +// ************************* VALUE DESCRIPTORS ***************************** + +// Add a value descriptor +// 409 - Formatting is bad or it is not unique +// 503 - Unexpected +// TODO: Check for valid printf formatting +func (mc *MongoClient) AddValueDescriptor(v models.ValueDescriptor) (bson.ObjectId, error) { + s := mc.getSessionCopy() + defer s.Close() + + // Created/Modified now + v.Created = time.Now().UnixNano() / int64(time.Millisecond) + + // See if the name is unique and add the value descriptors + info, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Upsert(bson.M{"name": v.Name}, v) + if err != nil { + return v.Id, err + } + + // Duplicate name + if info.UpsertedId == nil { + return v.Id, db.ErrNotUnique + } + + // Set ID + v.Id = info.UpsertedId.(bson.ObjectId) + + return v.Id, err +} + +// Return a list of all the value descriptors +// 513 Service Unavailable - database problems +func (mc *MongoClient) ValueDescriptors() ([]models.ValueDescriptor, error) { + return mc.getValueDescriptors(nil) +} + +// Update a value descriptor +// First use the ID for identification, then the name +// TODO: Check for the valid printf formatting +// 404 not found if the value descriptor cannot be found by the identifiers +func (mc *MongoClient) UpdateValueDescriptor(v models.ValueDescriptor) error { + s := mc.getSessionCopy() + defer s.Close() + + // See if the name is unique if it changed + vd, err := mc.getValueDescriptor(bson.M{"name": v.Name}) + if err != db.ErrNotFound { + if err != nil { + return err + } + + // IDs are different -> name not unique + if vd.Id != v.Id { + return db.ErrNotUnique + } + } + + v.Modified = time.Now().UnixNano() / int64(time.Millisecond) + + err = s.DB(mc.database.Name).C(db.ValueDescriptorCollection).UpdateId(v.Id, v) + if err == mgo.ErrNotFound { + return db.ErrNotFound + } + return err +} + +// Delete the value descriptor based on the id +// Not found error if there isn't a value descriptor for the ID +// ValueDescriptorStillInUse if the value descriptor is still referenced by readings +func (mc *MongoClient) DeleteValueDescriptorById(id string) error { + if !bson.IsObjectIdHex(id) { + return db.ErrInvalidObjectId + } + return mc.deleteById(db.ValueDescriptorCollection, id) +} + +// Return a value descriptor based on the name +// Can return null if no value descriptor is found +func (mc *MongoClient) ValueDescriptorByName(name string) (models.ValueDescriptor, error) { + query := bson.M{"name": name} + return mc.getValueDescriptor(query) +} + +// Return all of the value descriptors based on the names +func (mc *MongoClient) ValueDescriptorsByName(names []string) ([]models.ValueDescriptor, error) { + vList := []models.ValueDescriptor{} + + for _, name := range names { + v, err := mc.ValueDescriptorByName(name) + if err != nil && err != db.ErrNotFound { + return []models.ValueDescriptor{}, err + } + if err == nil { + vList = append(vList, v) + } + } + + return vList, nil +} + +// Return a value descriptor based on the id +// Return NotFoundError if there is no value descriptor for the id +func (mc *MongoClient) ValueDescriptorById(id string) (models.ValueDescriptor, error) { + if !bson.IsObjectIdHex(id) { + return models.ValueDescriptor{}, db.ErrInvalidObjectId + } + + query := bson.M{"_id": bson.ObjectIdHex(id)} + return mc.getValueDescriptor(query) +} + +// Return all the value descriptors that match the UOM label +func (mc *MongoClient) ValueDescriptorsByUomLabel(uomLabel string) ([]models.ValueDescriptor, error) { + query := bson.M{"uomLabel": uomLabel} + return mc.getValueDescriptors(query) +} + +// Return value descriptors based on if it has the label +func (mc *MongoClient) ValueDescriptorsByLabel(label string) ([]models.ValueDescriptor, error) { + query := bson.M{"labels": label} + return mc.getValueDescriptors(query) +} + +// Return value descriptors based on the type +func (mc *MongoClient) ValueDescriptorsByType(t string) ([]models.ValueDescriptor, error) { + query := bson.M{"type": t} + return mc.getValueDescriptors(query) +} + +// Delete all of the value descriptors +func (mc *MongoClient) ScrubAllValueDescriptors() error { + s := mc.getSessionCopy() + defer s.Close() + + _, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).RemoveAll(nil) + if err != nil { + return err + } + + return nil +} + +// Get value descriptors based on the query +func (mc *MongoClient) getValueDescriptors(q bson.M) ([]models.ValueDescriptor, error) { + s := mc.getSessionCopy() + defer s.Close() + + v := []models.ValueDescriptor{} + err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).All(&v) + + return v, err +} + +// Get value descriptors with a limit based on the query +func (mc *MongoClient) getValueDescriptorsLimit(q bson.M, limit int) ([]models.ValueDescriptor, error) { + s := mc.getSessionCopy() + defer s.Close() + + v := []models.ValueDescriptor{} + err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).Limit(limit).All(&v) + + return v, err +} + +// Get a value descriptor based on the query +func (mc *MongoClient) getValueDescriptor(q bson.M) (models.ValueDescriptor, error) { + s := mc.getSessionCopy() + defer s.Close() + + var v models.ValueDescriptor + err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Find(q).One(&v) + if err == mgo.ErrNotFound { + return v, db.ErrNotFound + } + + return v, err +} diff --git a/core/db/mongo/metadata.go b/core/db/mongo/metadata.go index ec555cdfe9..9323c703c9 100644 --- a/core/db/mongo/metadata.go +++ b/core/db/mongo/metadata.go @@ -15,12 +15,10 @@ package mongo import ( "errors" - "strconv" "time" "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" - "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) @@ -28,35 +26,6 @@ func makeTimestamp() int64 { return time.Now().UnixNano() / int64(time.Millisecond) } -func (m *MongoClient) Connect() error { - // Create the dial info for the Mongo session - connectionString := m.config.Host + ":" + strconv.Itoa(m.config.Port) - mongoDBDialInfo := &mgo.DialInfo{ - Addrs: []string{connectionString}, - Timeout: time.Duration(m.config.Timeout) * time.Millisecond, - Database: m.config.DatabaseName, - Username: m.config.Username, - Password: m.config.Password, - } - session, err := mgo.DialWithInfo(mongoDBDialInfo) - if err != nil { - return err - } - - m.session = session - m.database = session.DB(m.config.DatabaseName) - currentMongoClient = m // Set the singleton - - return nil -} - -func (m *MongoClient) CloseSession() { - if m.session != nil { - m.session.Close() - m.session = nil - } -} - /* -----------------------Schedule Event ------------------------*/ func (m *MongoClient) UpdateScheduleEvent(se models.ScheduleEvent) error { s := m.session.Copy() From e1df020fe344e0c7a815e93cb5e2f61b3bebe265 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Mon, 18 Jun 2018 11:36:18 +0200 Subject: [PATCH 08/10] core/db: Move MakeTimestamp to core/db Also made all databases to use this functions when obtaining a timestamp Signed-off-by: Federico Claramonte --- core/db/db.go | 9 ++++++++- core/db/influx/data.go | 14 +++++++------- core/db/memory/data.go | 10 ++++------ core/db/memory/metadata.go | 23 +++++++++++------------ core/db/mongo/data.go | 16 +++++++--------- core/db/mongo/metadata.go | 33 ++++++++++++++------------------- core/db/test/db_data.go | 10 +++++----- 7 files changed, 56 insertions(+), 59 deletions(-) diff --git a/core/db/db.go b/core/db/db.go index e5cf9c5eae..9a42e1c4fe 100644 --- a/core/db/db.go +++ b/core/db/db.go @@ -14,7 +14,10 @@ package db -import "errors" +import ( + "errors" + "time" +) const ( // Data @@ -50,3 +53,7 @@ type Configuration struct { Username string Password string } + +func MakeTimestamp() int64 { + return time.Now().UnixNano() / int64(time.Millisecond) +} diff --git a/core/db/influx/data.go b/core/db/influx/data.go index 8ba7745385..7327f01d21 100644 --- a/core/db/influx/data.go +++ b/core/db/influx/data.go @@ -39,7 +39,7 @@ func (ic *InfluxClient) Events() ([]models.Event, error) { // UnexpectedError - failed to add to database // NoValueDescriptor - no existing value descriptor for a reading in the event func (ic *InfluxClient) AddEvent(e *models.Event) (bson.ObjectId, error) { - e.Created = time.Now().UnixNano() / int64(time.Millisecond) + e.Created = db.MakeTimestamp() e.ID = bson.NewObjectId() // Add the event @@ -55,7 +55,7 @@ func (ic *InfluxClient) AddEvent(e *models.Event) (bson.ObjectId, error) { // UnexpectedError - problem updating in database // NotFound - no event with the ID was found func (ic *InfluxClient) UpdateEvent(e models.Event) error { - e.Modified = time.Now().UnixNano() / int64(time.Millisecond) + e.Modified = db.MakeTimestamp() // Delete event if err := ic.deleteById(db.EventsCollection, e.ID.Hex()); err != nil { @@ -119,7 +119,7 @@ func (ic *InfluxClient) EventsByCreationTime(startTime, endTime int64, limit int // Get Events that are older than the given age (defined by age = now - created) func (ic *InfluxClient) EventsOlderThanAge(age int64) ([]models.Event, error) { - expireDate := (time.Now().UnixNano() / int64(time.Millisecond)) - age + expireDate := db.MakeTimestamp() - age query := fmt.Sprintf("WHERE created < %d", expireDate) return ic.getEvents(query) } @@ -305,7 +305,7 @@ func (ic *InfluxClient) Readings() ([]models.Reading, error) { func (ic *InfluxClient) AddReading(r models.Reading) (bson.ObjectId, error) { // Get the reading ready r.Id = bson.NewObjectId() - r.Created = time.Now().UnixNano() / int64(time.Millisecond) + r.Created = db.MakeTimestamp() err := ic.addReadingToDB(ic.Database, db.ReadingsCollection, &r) return r.Id, err } @@ -315,7 +315,7 @@ func (ic *InfluxClient) AddReading(r models.Reading) (bson.ObjectId, error) { // 409 - Value descriptor doesn't exist // 503 - unknown issues func (ic *InfluxClient) UpdateReading(r models.Reading) error { - r.Modified = time.Now().UnixNano() / int64(time.Millisecond) + r.Modified = db.MakeTimestamp() // Delete reading if err := ic.deleteById(db.ReadingsCollection, r.Id.Hex()); err != nil { @@ -508,7 +508,7 @@ func parseReadings(res client.Result) ([]models.Reading, error) { // TODO: Check for valid printf formatting func (ic *InfluxClient) AddValueDescriptor(v models.ValueDescriptor) (bson.ObjectId, error) { // Created/Modified now - v.Created = time.Now().UnixNano() / int64(time.Millisecond) + v.Created = db.MakeTimestamp() // See if the name is unique and add the value descriptors query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE 'name' = '%s'", db.ValueDescriptorCollection, v.Name) @@ -566,7 +566,7 @@ func (ic *InfluxClient) UpdateValueDescriptor(v models.ValueDescriptor) error { return err } } - v.Modified = time.Now().UnixNano() / int64(time.Millisecond) + v.Modified = db.MakeTimestamp() // Delete Value Descriptor // Add Value Descriptor return ic.addValueDescriptorToDB(ic.Database, db.ValueDescriptorCollection, &v) diff --git a/core/db/memory/data.go b/core/db/memory/data.go index 64cca910ec..d13a4988a5 100644 --- a/core/db/memory/data.go +++ b/core/db/memory/data.go @@ -14,15 +14,13 @@ package memory import ( - "time" - "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2/bson" ) func (m *MemDB) AddReading(r models.Reading) (bson.ObjectId, error) { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() r.Created = currentTime r.Modified = currentTime r.Id = bson.NewObjectId() @@ -37,7 +35,7 @@ func (m *MemDB) Events() ([]models.Event, error) { } func (m *MemDB) AddEvent(e *models.Event) (bson.ObjectId, error) { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() for i := range e.Readings { e.Readings[i].Id = bson.NewObjectId() @@ -155,7 +153,7 @@ func (m *MemDB) ReadingsByDeviceAndValueDescriptor(deviceId, valueDescriptor str } func (m *MemDB) EventsOlderThanAge(age int64) ([]models.Event, error) { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() events := []models.Event{} for _, e := range m.events { if currentTime-e.Created >= age { @@ -279,7 +277,7 @@ func (m *MemDB) ReadingsByCreationTime(start, end int64, limit int) ([]models.Re } func (m *MemDB) AddValueDescriptor(value models.ValueDescriptor) (bson.ObjectId, error) { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() value.Created = currentTime value.Modified = currentTime value.Id = bson.NewObjectId() diff --git a/core/db/memory/metadata.go b/core/db/memory/metadata.go index 5735622bea..c4746f9ddc 100644 --- a/core/db/memory/metadata.go +++ b/core/db/memory/metadata.go @@ -17,7 +17,6 @@ package memory import ( "errors" "fmt" - "time" "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" @@ -33,7 +32,7 @@ func (m *MemDB) GetAllScheduleEvents(se *[]models.ScheduleEvent) error { } func (m *MemDB) AddScheduleEvent(se *models.ScheduleEvent) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() se.Created = currentTime se.Modified = currentTime se.Id = bson.NewObjectId() @@ -172,7 +171,7 @@ func (m *MemDB) GetAllSchedules(s *[]models.Schedule) error { } func (m *MemDB) AddSchedule(s *models.Schedule) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() s.Created = currentTime s.Modified = currentTime s.Id = bson.NewObjectId() @@ -198,7 +197,7 @@ func (m *MemDB) GetScheduleByName(s *models.Schedule, n string) error { } func (m *MemDB) UpdateSchedule(s models.Schedule) error { - s.Modified = time.Now().UnixNano() / int64(time.Millisecond) + s.Modified = db.MakeTimestamp() for i, ss := range m.schedules { if ss.Id == s.Id { m.schedules[i] = s @@ -269,7 +268,7 @@ func (m *MemDB) GetDeviceReportById(dr *models.DeviceReport, id string) error { } func (m *MemDB) AddDeviceReport(dr *models.DeviceReport) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() dr.Created = currentTime dr.Modified = currentTime dr.Id = bson.NewObjectId() @@ -424,7 +423,7 @@ func (m *MemDB) GetDevicesWithLabel(d *[]models.Device, l string) error { } func (m *MemDB) AddDevice(d *models.Device) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() d.Created = currentTime d.Modified = currentTime d.Id = bson.NewObjectId() @@ -477,7 +476,7 @@ func (m *MemDB) UpdateDeviceProfile(dp *models.DeviceProfile) error { } func (m *MemDB) AddDeviceProfile(d *models.DeviceProfile) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() d.Created = currentTime d.Modified = currentTime d.Id = bson.NewObjectId() @@ -617,7 +616,7 @@ func (m *MemDB) UpdateAddressable(updated *models.Addressable, orig *models.Addr } func (m *MemDB) AddAddressable(a *models.Addressable) (bson.ObjectId, error) { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() a.Created = currentTime a.Modified = currentTime a.Id = bson.NewObjectId() @@ -805,7 +804,7 @@ func (m *MemDB) GetAllDeviceServices(d *[]models.DeviceService) error { } func (m *MemDB) AddDeviceService(ds *models.DeviceService) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() ds.Created = currentTime ds.Modified = currentTime ds.Id = bson.NewObjectId() @@ -974,7 +973,7 @@ func (m *MemDB) updateProvisionWatcherValues(pw *models.ProvisionWatcher) error } func (m *MemDB) AddProvisionWatcher(pw *models.ProvisionWatcher) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() pw.Created = currentTime pw.Modified = currentTime pw.Id = bson.NewObjectId() @@ -992,7 +991,7 @@ func (m *MemDB) AddProvisionWatcher(pw *models.ProvisionWatcher) error { } func (m *MemDB) UpdateProvisionWatcher(pw models.ProvisionWatcher) error { - pw.Modified = time.Now().UnixNano() / int64(time.Millisecond) + pw.Modified = db.MakeTimestamp() if err := m.updateProvisionWatcherValues(&pw); err != nil { return err @@ -1039,7 +1038,7 @@ func (m *MemDB) GetCommandByName(d *[]models.Command, name string) error { } func (m *MemDB) AddCommand(c *models.Command) error { - currentTime := time.Now().UnixNano() / int64(time.Millisecond) + currentTime := db.MakeTimestamp() c.Created = currentTime c.Modified = currentTime c.Id = bson.NewObjectId() diff --git a/core/db/mongo/data.go b/core/db/mongo/data.go index 4d688a6778..03dab1762b 100644 --- a/core/db/mongo/data.go +++ b/core/db/mongo/data.go @@ -14,8 +14,6 @@ package mongo import ( - "time" - "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" mgo "gopkg.in/mgo.v2" @@ -43,7 +41,7 @@ func (mc *MongoClient) AddEvent(e *models.Event) (bson.ObjectId, error) { s := mc.getSessionCopy() defer s.Close() - e.Created = time.Now().UnixNano() / int64(time.Millisecond) + e.Created = db.MakeTimestamp() e.ID = bson.NewObjectId() // Insert readings @@ -80,7 +78,7 @@ func (mc *MongoClient) UpdateEvent(e models.Event) error { s := mc.getSessionCopy() defer s.Close() - e.Modified = time.Now().UnixNano() / int64(time.Millisecond) + e.Modified = db.MakeTimestamp() // Handle DBRef me := mongoEvent{Event: e} @@ -147,7 +145,7 @@ func (mc *MongoClient) EventsByCreationTime(startTime, endTime int64, limit int) // Get Events that are older than the given age (defined by age = now - created) func (mc *MongoClient) EventsOlderThanAge(age int64) ([]models.Event, error) { - expireDate := (time.Now().UnixNano() / int64(time.Millisecond)) - age + expireDate := (db.MakeTimestamp()) - age return mc.getEvents(bson.M{"created": bson.M{"$lt": expireDate}}) } @@ -251,7 +249,7 @@ func (mc *MongoClient) AddReading(r models.Reading) (bson.ObjectId, error) { // Get the reading ready r.Id = bson.NewObjectId() - r.Created = time.Now().UnixNano() / int64(time.Millisecond) + r.Created = db.MakeTimestamp() err := s.DB(mc.database.Name).C(db.ReadingsCollection).Insert(&r) return r.Id, err @@ -265,7 +263,7 @@ func (mc *MongoClient) UpdateReading(r models.Reading) error { s := mc.getSessionCopy() defer s.Close() - r.Modified = time.Now().UnixNano() / int64(time.Millisecond) + r.Modified = db.MakeTimestamp() // Update the reading err := s.DB(mc.database.Name).C(db.ReadingsCollection).UpdateId(r.Id, r) @@ -393,7 +391,7 @@ func (mc *MongoClient) AddValueDescriptor(v models.ValueDescriptor) (bson.Object defer s.Close() // Created/Modified now - v.Created = time.Now().UnixNano() / int64(time.Millisecond) + v.Created = db.MakeTimestamp() // See if the name is unique and add the value descriptors info, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).Upsert(bson.M{"name": v.Name}, v) @@ -439,7 +437,7 @@ func (mc *MongoClient) UpdateValueDescriptor(v models.ValueDescriptor) error { } } - v.Modified = time.Now().UnixNano() / int64(time.Millisecond) + v.Modified = db.MakeTimestamp() err = s.DB(mc.database.Name).C(db.ValueDescriptorCollection).UpdateId(v.Id, v) if err == mgo.ErrNotFound { diff --git a/core/db/mongo/metadata.go b/core/db/mongo/metadata.go index 9323c703c9..e93166a8c6 100644 --- a/core/db/mongo/metadata.go +++ b/core/db/mongo/metadata.go @@ -15,24 +15,19 @@ package mongo import ( "errors" - "time" "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2/bson" ) -func makeTimestamp() int64 { - return time.Now().UnixNano() / int64(time.Millisecond) -} - /* -----------------------Schedule Event ------------------------*/ func (m *MongoClient) UpdateScheduleEvent(se models.ScheduleEvent) error { s := m.session.Copy() defer s.Close() col := s.DB(m.database.Name).C(db.ScheduleEvent) - se.Modified = makeTimestamp() + se.Modified = db.MakeTimestamp() // Handle DBRefs mse := mongoScheduleEvent{ScheduleEvent: se} @@ -50,7 +45,7 @@ func (m *MongoClient) AddScheduleEvent(se *models.ScheduleEvent) error { } else if count > 0 { return db.ErrNotUnique } - ts := makeTimestamp() + ts := db.MakeTimestamp() se.Created = ts se.Modified = ts se.Id = bson.NewObjectId() @@ -167,7 +162,7 @@ func (m *MongoClient) AddSchedule(sch *models.Schedule) error { return db.ErrNotUnique } - ts := makeTimestamp() + ts := db.MakeTimestamp() sch.Created = ts sch.Modified = ts sch.Id = bson.NewObjectId() @@ -179,7 +174,7 @@ func (m *MongoClient) UpdateSchedule(sch models.Schedule) error { defer s.Close() col := s.DB(m.database.Name).C(db.Schedule) - sch.Modified = makeTimestamp() + sch.Modified = db.MakeTimestamp() if err := col.UpdateId(sch.Id, sch); err != nil { return err @@ -256,7 +251,7 @@ func (m *MongoClient) AddDeviceReport(d *models.DeviceReport) error { } else if count > 0 { return db.ErrNotUnique } - ts := makeTimestamp() + ts := db.MakeTimestamp() d.Created = ts d.Id = bson.NewObjectId() return col.Insert(d) @@ -288,7 +283,7 @@ func (m *MongoClient) AddDevice(d *models.Device) error { if count > 0 { return db.ErrNotUnique } - ts := makeTimestamp() + ts := db.MakeTimestamp() d.Created = ts d.Modified = ts d.Id = bson.NewObjectId() @@ -486,7 +481,7 @@ func (m *MongoClient) AddDeviceProfile(dp *models.DeviceProfile) error { return err } } - ts := makeTimestamp() + ts := db.MakeTimestamp() dp.Created = ts dp.Modified = ts dp.Id = bson.NewObjectId() @@ -502,7 +497,7 @@ func (m *MongoClient) UpdateDeviceProfile(dp *models.DeviceProfile) error { c := s.DB(m.database.Name).C(db.DeviceProfile) mdp := mongoDeviceProfile{DeviceProfile: *dp} - mdp.Modified = makeTimestamp() + mdp.Modified = db.MakeTimestamp() return c.UpdateId(mdp.Id, mdp) } @@ -597,7 +592,7 @@ func (m *MongoClient) AddAddressable(a *models.Addressable) (bson.ObjectId, erro return a.Id, db.ErrNotUnique } - ts := makeTimestamp() + ts := db.MakeTimestamp() a.Created = ts a.Id = bson.NewObjectId() err = col.Insert(a) @@ -709,7 +704,7 @@ func (m *MongoClient) AddDeviceService(d *models.DeviceService) error { col := s.DB(m.database.Name).C(db.DeviceService) - ts := makeTimestamp() + ts := db.MakeTimestamp() d.Created = ts d.Modified = ts d.Id = bson.NewObjectId() @@ -724,7 +719,7 @@ func (m *MongoClient) UpdateDeviceService(deviceService models.DeviceService) er defer s.Close() c := s.DB(m.database.Name).C(db.DeviceService) - deviceService.Modified = makeTimestamp() + deviceService.Modified = db.MakeTimestamp() // Handle DBRefs mds := mongoDeviceService{DeviceService: deviceService} @@ -848,7 +843,7 @@ func (m *MongoClient) AddProvisionWatcher(pw *models.ProvisionWatcher) error { pw.Profile = dp // Set data - ts := makeTimestamp() + ts := db.MakeTimestamp() pw.Created = ts pw.Modified = ts pw.Id = bson.NewObjectId() @@ -864,7 +859,7 @@ func (m *MongoClient) UpdateProvisionWatcher(pw models.ProvisionWatcher) error { defer s.Close() c := s.DB(m.database.Name).C(db.ProvisionWatcher) - pw.Modified = makeTimestamp() + pw.Modified = db.MakeTimestamp() // Handle DBRefs mpw := mongoProvisionWatcher{ProvisionWatcher: pw} @@ -911,7 +906,7 @@ func (m *MongoClient) AddCommand(c *models.Command) error { defer s.Close() col := s.DB(m.database.Name).C(db.Command) - ts := makeTimestamp() + ts := db.MakeTimestamp() c.Created = ts c.Id = bson.NewObjectId() return col.Insert(c) diff --git a/core/db/test/db_data.go b/core/db/test/db_data.go index 8868e0314c..dc19b592a7 100644 --- a/core/db/test/db_data.go +++ b/core/db/test/db_data.go @@ -10,9 +10,9 @@ import ( "fmt" "strconv" "testing" - "time" "github.com/edgexfoundry/edgex-go/core/data/clients" + dbp "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2/bson" ) @@ -76,7 +76,7 @@ func testDBReadings(t *testing.T, db clients.DBClient) { t.Fatalf("Error removing all readings") } - beforeTime := time.Now().UnixNano() / int64(time.Millisecond) + beforeTime := dbp.MakeTimestamp() id, err := populateDbReadings(db, 100) if err != nil { t.Fatalf("Error populating db: %v\n", err) @@ -87,7 +87,7 @@ func testDBReadings(t *testing.T, db clients.DBClient) { if err != nil { t.Fatalf("Error populating db: %v\n", err) } - afterTime := time.Now().UnixNano() / int64(time.Millisecond) + afterTime := dbp.MakeTimestamp() count, err := db.ReadingCount() if err != nil { @@ -270,7 +270,7 @@ func testDBEvents(t *testing.T, db clients.DBClient) { t.Fatalf("Error removing all events") } - beforeTime := time.Now().UnixNano() / int64(time.Millisecond) + beforeTime := dbp.MakeTimestamp() id, err := populateDbEvents(db, 100, 0) if err != nil { t.Fatalf("Error populating db: %v\n", err) @@ -281,7 +281,7 @@ func testDBEvents(t *testing.T, db clients.DBClient) { if err != nil { t.Fatalf("Error populating db: %v\n", err) } - afterTime := time.Now().UnixNano() / int64(time.Millisecond) + afterTime := dbp.MakeTimestamp() count, err := db.EventCount() if err != nil { From 9e847c16111d7b0a5f4c5eb272c6c0a71b30ae98 Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Tue, 19 Jun 2018 12:04:42 +0200 Subject: [PATCH 09/10] core: Unified core and metadata db interfaces package name Signed-off-by: Federico Claramonte --- core/data/init.go | 14 ++++++------ .../database-client.go => interfaces/db.go} | 2 +- core/db/test/db_data.go | 22 +++++++++---------- core/metadata/interfaces/{dbOps.go => db.go} | 0 4 files changed, 19 insertions(+), 19 deletions(-) rename core/data/{clients/database-client.go => interfaces/db.go} (99%) rename core/metadata/interfaces/{dbOps.go => db.go} (100%) diff --git a/core/data/init.go b/core/data/init.go index 331a5b5287..fb156a5012 100644 --- a/core/data/init.go +++ b/core/data/init.go @@ -19,7 +19,7 @@ import ( "github.com/edgexfoundry/edgex-go/core/clients/metadata" "github.com/edgexfoundry/edgex-go/core/clients/types" - "github.com/edgexfoundry/edgex-go/core/data/clients" + "github.com/edgexfoundry/edgex-go/core/data/interfaces" "github.com/edgexfoundry/edgex-go/core/data/messaging" "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/db/influx" @@ -31,7 +31,7 @@ import ( ) // Global variables -var dbc clients.DBClient +var dbc interfaces.DBClient var loggingClient logger.LoggingClient var ep *messaging.EventPublisher var mdc metadata.DeviceClient @@ -62,12 +62,12 @@ func ConnectToConsul(conf ConfigurationStruct) error { } // Return the dbClient interface -func newDBClient(dbType clients.DatabaseType, config db.Configuration) (clients.DBClient, error) { +func newDBClient(dbType interfaces.DatabaseType, config db.Configuration) (interfaces.DBClient, error) { switch dbType { - case clients.MONGO: + case interfaces.MONGO: // Create the mongo client return mongo.NewClient(config), nil - case clients.INFLUX: + case interfaces.INFLUX: // Create the influx client ic, err := influx.NewClient(config) if err != nil { @@ -75,7 +75,7 @@ func newDBClient(dbType clients.DatabaseType, config db.Configuration) (clients. return nil, err } return ic, nil - case clients.MEMORY: + case interfaces.MEMORY: // Create the memory client return &memory.MemDB{}, nil default: @@ -91,7 +91,7 @@ func Init(conf ConfigurationStruct, l logger.LoggingClient, useConsul bool) erro var err error // Create a database client - dbc, err = newDBClient(clients.MONGO, db.Configuration{ + dbc, err = newDBClient(interfaces.MONGO, db.Configuration{ Host: conf.MongoDBHost, Port: conf.MongoDBPort, Timeout: conf.MongoDBConnectTimeout, diff --git a/core/data/clients/database-client.go b/core/data/interfaces/db.go similarity index 99% rename from core/data/clients/database-client.go rename to core/data/interfaces/db.go index f1db9496c7..2b3b318aac 100644 --- a/core/data/clients/database-client.go +++ b/core/data/interfaces/db.go @@ -11,7 +11,7 @@ * or implied. See the License for the specific language governing permissions and limitations under * the License. *******************************************************************************/ -package clients +package interfaces import ( "github.com/edgexfoundry/edgex-go/core/domain/models" diff --git a/core/db/test/db_data.go b/core/db/test/db_data.go index dc19b592a7..748a02bbb1 100644 --- a/core/db/test/db_data.go +++ b/core/db/test/db_data.go @@ -11,13 +11,13 @@ import ( "strconv" "testing" - "github.com/edgexfoundry/edgex-go/core/data/clients" + "github.com/edgexfoundry/edgex-go/core/data/interfaces" dbp "github.com/edgexfoundry/edgex-go/core/db" "github.com/edgexfoundry/edgex-go/core/domain/models" "gopkg.in/mgo.v2/bson" ) -func populateDbReadings(db clients.DBClient, count int) (bson.ObjectId, error) { +func populateDbReadings(db interfaces.DBClient, count int) (bson.ObjectId, error) { var id bson.ObjectId for i := 0; i < count; i++ { name := fmt.Sprintf("name%d", i) @@ -34,7 +34,7 @@ func populateDbReadings(db clients.DBClient, count int) (bson.ObjectId, error) { return id, nil } -func populateDbValues(db clients.DBClient, count int) (bson.ObjectId, error) { +func populateDbValues(db interfaces.DBClient, count int) (bson.ObjectId, error) { var id bson.ObjectId for i := 0; i < count; i++ { name := fmt.Sprintf("name%d", i) @@ -53,7 +53,7 @@ func populateDbValues(db clients.DBClient, count int) (bson.ObjectId, error) { return id, nil } -func populateDbEvents(db clients.DBClient, count int, pushed int64) (bson.ObjectId, error) { +func populateDbEvents(db interfaces.DBClient, count int, pushed int64) (bson.ObjectId, error) { var id bson.ObjectId for i := 0; i < count; i++ { name := fmt.Sprintf("name%d", i) @@ -70,7 +70,7 @@ func populateDbEvents(db clients.DBClient, count int, pushed int64) (bson.Object return id, nil } -func testDBReadings(t *testing.T, db clients.DBClient) { +func testDBReadings(t *testing.T, db interfaces.DBClient) { err := db.ScrubAllEvents() if err != nil { t.Fatalf("Error removing all readings") @@ -264,7 +264,7 @@ func testDBReadings(t *testing.T, db clients.DBClient) { } } -func testDBEvents(t *testing.T, db clients.DBClient) { +func testDBEvents(t *testing.T, db interfaces.DBClient) { err := db.ScrubAllEvents() if err != nil { t.Fatalf("Error removing all events") @@ -467,7 +467,7 @@ func testDBEvents(t *testing.T, db clients.DBClient) { } } -func testDBValueDescriptors(t *testing.T, db clients.DBClient) { +func testDBValueDescriptors(t *testing.T, db interfaces.DBClient) { err := db.ScrubAllValueDescriptors() if err != nil { t.Fatalf("Error removing all value descriptors") @@ -618,7 +618,7 @@ func testDBValueDescriptors(t *testing.T, db clients.DBClient) { } } -func TestDataDB(t *testing.T, db clients.DBClient) { +func TestDataDB(t *testing.T, db interfaces.DBClient) { err := db.Connect() if err != nil { @@ -635,14 +635,14 @@ func TestDataDB(t *testing.T, db clients.DBClient) { db.CloseSession() } -func BenchmarkDB(b *testing.B, db clients.DBClient) { +func BenchmarkDB(b *testing.B, db interfaces.DBClient) { benchmarkReadings(b, db) benchmarkEvents(b, db) db.CloseSession() } -func benchmarkReadings(b *testing.B, db clients.DBClient) { +func benchmarkReadings(b *testing.B, db interfaces.DBClient) { // Remove previous events and readings db.ScrubAllEvents() @@ -706,7 +706,7 @@ func benchmarkReadings(b *testing.B, db clients.DBClient) { }) } -func benchmarkEvents(b *testing.B, db clients.DBClient) { +func benchmarkEvents(b *testing.B, db interfaces.DBClient) { // Remove previous events and readings db.ScrubAllEvents() diff --git a/core/metadata/interfaces/dbOps.go b/core/metadata/interfaces/db.go similarity index 100% rename from core/metadata/interfaces/dbOps.go rename to core/metadata/interfaces/db.go From 2e93d65cdb6cf68b13a36f0baffe80f5d682a92e Mon Sep 17 00:00:00 2001 From: Federico Claramonte Date: Tue, 19 Jun 2018 16:15:23 +0200 Subject: [PATCH 10/10] Remove commented struct Signed-off-by: Federico Claramonte --- core/db/mongo/device_profile.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/core/db/mongo/device_profile.go b/core/db/mongo/device_profile.go index 4442b60adc..dcbec989bb 100644 --- a/core/db/mongo/device_profile.go +++ b/core/db/mongo/device_profile.go @@ -59,19 +59,6 @@ func (mdp mongoDeviceProfile) GetBSON() (interface{}, error) { }, nil } -// type temp struct { -// models.DescribedObject `bson:",inline"` -// Id bson.ObjectId `bson:"_id,omitempty"` -// Name string `bson:"name"` // Non-database identifier (must be unique) -// Manufacturer string `bson:"manufacturer"` // Manufacturer of the device -// Model string `bson:"model"` // Model of the device -// Labels []string `bson:"labels"` // Labels used to search for groups of profiles -// Objects interface{} `bson:"objects"` // JSON data that the device service uses to communicate with devices with this profile -// DeviceResources []models.DeviceObject `bson:"deviceResources"` -// Resources []models.ProfileResource `bson:"resources"` -// Commands []mgo.DBRef `bson:"commands"` // List of commands to Get/Put information for devices associated with this profile -// } - // Custom unmarshaling out of mongo func (mdp *mongoDeviceProfile) SetBSON(raw bson.Raw) error { decoded := new(struct {