Skip to content

Commit

Permalink
allow deletion of data instance by data UUID
Browse files Browse the repository at this point in the history
  • Loading branch information
DocSavage committed Jun 5, 2024
1 parent daec88c commit f098b60
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 61 deletions.
26 changes: 14 additions & 12 deletions datastore/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,28 +406,30 @@ func GetDataByVersionName(v dvid.VersionID, name dvid.InstanceName) (DataService
return manager.getDataByVersionName(v, name)
}

// DeleteDataByName returns a data service given an instance name and UUID.
// DeleteDataByName deletes a data service given an instance name and UUID.
func DeleteDataByName(uuid dvid.UUID, name dvid.InstanceName, passcode string) error {
if manager == nil {
return ErrManagerNotInitialized
data, err := GetDataByUUIDName(uuid, name)
if err != nil {
return err
}
return manager.deleteDataByName(uuid, name, passcode)
return manager.deleteData(data, passcode)
}

// RenameData renames a data service given an old instance name and UUID.
func RenameData(uuid dvid.UUID, oldname, newname dvid.InstanceName, passcode string) error {
if manager == nil {
return ErrManagerNotInitialized
// DeleteDataByDataUUID deletes a data service given a data UUID
func DeleteDataByDataUUID(dataUUID dvid.UUID, passcode string) error {
data, err := GetDataByDataUUID(dataUUID)
if err != nil {
return err
}
return manager.renameDataByName(uuid, oldname, newname, passcode)
return manager.deleteData(data, passcode)
}

// DeleteDataByVersion returns a data service given an instance name and UUID.
func DeleteDataByVersion(v dvid.VersionID, name dvid.InstanceName, passcode string) error {
// RenameData renames a data service given an old instance name and UUID.
func RenameData(uuid dvid.UUID, oldname, newname dvid.InstanceName, passcode string) error {
if manager == nil {
return ErrManagerNotInitialized
}
return manager.deleteDataByVersion(v, name, passcode)
return manager.renameDataByName(uuid, oldname, newname, passcode)
}

func ModifyDataConfigByName(uuid dvid.UUID, name dvid.InstanceName, c dvid.Config) error {
Expand Down
83 changes: 48 additions & 35 deletions datastore/repo_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ func (m *repoManager) loadVersion0() error {
}
for name, data := range r.data {
if data.IsDeleted() {
if err := r.deleteData(name); err != nil {
if err := r.deleteDataByName(name); err != nil {
dvid.TimeCriticalf("tried to restart deletion of data %q but failed: %v\n", name, err)
}
}
Expand Down Expand Up @@ -2320,20 +2320,19 @@ func (m *repoManager) renameDataByName(uuid dvid.UUID, oldname, newname dvid.Ins

// deleteDataByName deletes all data associated with the data instance and removes
// it from the Repo.
func (m *repoManager) deleteDataByName(uuid dvid.UUID, name dvid.InstanceName, passcode string) error {
r, err := m.repoFromUUID(uuid)
func (m *repoManager) deleteData(data DataService, passcode string) error {
r, err := m.repoFromUUID(data.RootUUID())
if err != nil {
return err
}
return r.deleteDataWithPasscode(name, passcode)
}
if r.passcodeOK(passcode) {
data.SetDeleted(true)
go r.deleteData(data)
} else {
return fmt.Errorf("incorrect passcode for repo %s", r.uuid)

func (m *repoManager) deleteDataByVersion(v dvid.VersionID, name dvid.InstanceName, passcode string) error {
r, err := m.repoFromVersion(v)
if err != nil {
return err
}
return r.deleteDataWithPasscode(name, passcode)
return nil
}

// modifyData modifies preexisting Data within a Repo. Settings can be passed
Expand Down Expand Up @@ -2427,17 +2426,48 @@ func (r *repoT) branchHeads() map[string]dvid.UUID {
return branchToUUID
}

// For all data tiers of storage, remove data kv pairs associated with this data instance.
// This can be called asynchronously since it can be time-consuming.
func (r *repoT) deleteData(data DataService) {
if err := storage.DeleteDataInstance(data); err != nil {
dvid.Errorf("Error trying to do async data instance deletion: %v\n", err)
}

// Delete entries in the sync graph if this data needs to be synced with another data instance.
_, syncable := data.(Syncer)
if syncable {
r.deleteSyncGraph(data, false)
}

// Remove this data instance from the repository and persist.
r.Lock()
tm := time.Now()
r.updated = tm
msg := fmt.Sprintf("Delete data instance '%s' of type '%s'", data.DataName(), data.TypeName())
message := fmt.Sprintf("%s %s", tm.Format(time.RFC3339), msg)
r.log = append(r.log, message)
delete(r.data, data.DataName())
r.Unlock()
r.save()
}

func (r *repoT) passcodeOK(passcode string) bool {
r.RLock()
defer r.RUnlock()
return r.passcode == "" || r.passcode == passcode
}

func (r *repoT) deleteDataWithPasscode(name dvid.InstanceName, passcode string) error {
r.RLock()
if r.passcode != "" && r.passcode != passcode {
r.RUnlock()
return fmt.Errorf("incorrect passcode for repo %s", r.uuid)
}
r.RUnlock()
return r.deleteData(name)
return r.deleteDataByName(name)
}

func (r *repoT) deleteData(name dvid.InstanceName) error {
func (r *repoT) deleteDataByName(name dvid.InstanceName) error {
r.RLock()
data, found := r.data[name]
r.RUnlock()
Expand All @@ -2446,30 +2476,13 @@ func (r *repoT) deleteData(name dvid.InstanceName) error {
}
data.SetDeleted(true)

// For all data tiers of storage, remove data kv pairs associated with this instance id.
go func() {
if err := storage.DeleteDataInstance(data); err != nil {
dvid.Errorf("Error trying to do async data instance deletion: %v\n", err)
}

// Delete entries in the sync graph if this data needs to be synced with another data instance.
_, syncable := data.(Syncer)
if syncable {
r.deleteSyncGraph(data, false)
}

// Remove this data instance from the repository and persist.
r.Lock()
tm := time.Now()
r.updated = tm
msg := fmt.Sprintf("Delete data instance '%s' of type '%s'", name, data.TypeName())
message := fmt.Sprintf("%s %s", tm.Format(time.RFC3339), msg)
r.log = append(r.log, message)
delete(r.data, name)
r.Unlock()
r.save()
}()
go r.deleteData(data)
return nil
}

func (r *repoT) deleteDataByDataUUID(data DataService) error {
data.SetDeleted(true)
go r.deleteData(data)
return nil
}

Expand Down
27 changes: 13 additions & 14 deletions server/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ DANGEROUS COMMANDS (only available via command line)
Deletes an entire repo with the given root UUID.
repo <UUID> delete <data name> <repo passcode if any>
repo <UUID> delete <data name or UUID> <repo passcode if any>
Delete the given data instance.
Delete the given data instance. First checks by data UUID, and if a
data instance is not found, checks by name.
repo <UUID> make-master <old-master-branch-name>
Expand Down Expand Up @@ -674,24 +675,22 @@ func handleCommand(cmd *datastore.Request) (reply *datastore.Response, err error
*/

case "delete":
var dataname, passcode string
cmd.CommandArgs(3, &dataname, &passcode)
var dataId string // either data name or data UUID
var passcode string
cmd.CommandArgs(3, &dataId, &passcode)

// Make sure this instance exists.
if _, err = datastore.GetDataByUUIDName(uuid, dvid.InstanceName(dataname)); err != nil {
err = fmt.Errorf("Error trying to delete %q for UUID %s: %v", dataname, uuid, err)
return
// Try to delete a data UUID first, and if doesn't work, try by name.
if err = datastore.DeleteDataByDataUUID(dvid.UUID(dataId), passcode); err != nil {
err = datastore.DeleteDataByName(uuid, dvid.InstanceName(dataId), passcode)
}

// Do the deletion. Under hood, modifies metadata immediately and launches async k/v deletion.
if err = datastore.DeleteDataByName(uuid, dvid.InstanceName(dataname), passcode); err != nil {
err = fmt.Errorf("Error deleting data instance %q: %v", dataname, err)
if err != nil {
err = fmt.Errorf("error deleting data instance %q: %v", dataId, err)
return
}
reply.Text = fmt.Sprintf("Started deletion of data instance %q from repo with root %s\n", dataname, uuid)
reply.Text = fmt.Sprintf("Started deletion of data instance %q from repo with root %s\n", dataId, uuid)

default:
err = fmt.Errorf("Unknown command: %q", cmd)
err = fmt.Errorf("unknown command: %q", cmd)
return
}

Expand Down

0 comments on commit f098b60

Please sign in to comment.