github.com/cyverse/go-irodsclient@v0.13.2/irods/fs/resource.go (about)

     1  package fs
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  
     7  	"github.com/cyverse/go-irodsclient/irods/common"
     8  	"github.com/cyverse/go-irodsclient/irods/connection"
     9  	"github.com/cyverse/go-irodsclient/irods/message"
    10  	"github.com/cyverse/go-irodsclient/irods/types"
    11  	"github.com/cyverse/go-irodsclient/irods/util"
    12  	"golang.org/x/xerrors"
    13  )
    14  
    15  // GetResource returns a resource for the name
    16  func GetResource(conn *connection.IRODSConnection, name string) (*types.IRODSResource, error) {
    17  	if conn == nil || !conn.IsConnected() {
    18  		return nil, xerrors.Errorf("connection is nil or disconnected")
    19  	}
    20  
    21  	// lock the connection
    22  	conn.Lock()
    23  	defer conn.Unlock()
    24  
    25  	// query with AUTO_CLOSE option
    26  	query := message.NewIRODSMessageQueryRequest(1, 0, 0, 0x100)
    27  	query.AddSelect(common.ICAT_COLUMN_R_RESC_ID, 1)
    28  	query.AddSelect(common.ICAT_COLUMN_R_RESC_NAME, 1)
    29  	query.AddSelect(common.ICAT_COLUMN_R_ZONE_NAME, 1)
    30  	query.AddSelect(common.ICAT_COLUMN_R_TYPE_NAME, 1)
    31  	query.AddSelect(common.ICAT_COLUMN_R_CLASS_NAME, 1)
    32  	query.AddSelect(common.ICAT_COLUMN_R_LOC, 1)
    33  	query.AddSelect(common.ICAT_COLUMN_R_VAULT_PATH, 1)
    34  	query.AddSelect(common.ICAT_COLUMN_R_RESC_CONTEXT, 1)
    35  	query.AddSelect(common.ICAT_COLUMN_R_CREATE_TIME, 1)
    36  	query.AddSelect(common.ICAT_COLUMN_R_MODIFY_TIME, 1)
    37  
    38  	rescCondVal := fmt.Sprintf("= '%s'", name)
    39  	query.AddCondition(common.ICAT_COLUMN_R_RESC_NAME, rescCondVal)
    40  
    41  	queryResult := message.IRODSMessageQueryResponse{}
    42  	err := conn.Request(query, &queryResult, nil)
    43  	if err != nil {
    44  		return nil, xerrors.Errorf("failed to receive a resource query result message: %w", err)
    45  	}
    46  
    47  	err = queryResult.CheckError()
    48  	if err != nil {
    49  		return nil, xerrors.Errorf("received a data resource query error: %w", err)
    50  	}
    51  
    52  	// TODO: do we need to print out?
    53  	//if queryResult.ContinueIndex != 0 {
    54  	//	logger.Debugf("resource query for %s would have continued, more than one result found", name)
    55  	//}
    56  
    57  	if queryResult.RowCount == 0 {
    58  		return nil, xerrors.Errorf("no row found")
    59  	}
    60  
    61  	if queryResult.AttributeCount > len(queryResult.SQLResult) {
    62  		return nil, xerrors.Errorf("failed to receive resource attributes - requires %d, but received %d attributes", queryResult.AttributeCount, len(queryResult.SQLResult))
    63  	}
    64  
    65  	resource := &types.IRODSResource{}
    66  
    67  	for attr := 0; attr < queryResult.AttributeCount; attr++ {
    68  		sqlResult := queryResult.SQLResult[attr]
    69  		if len(sqlResult.Values) != queryResult.RowCount {
    70  			return nil, xerrors.Errorf("failed to receive resource rows - requires %d, but received %d attributes", queryResult.RowCount, len(sqlResult.Values))
    71  		}
    72  
    73  		value := sqlResult.Values[0]
    74  
    75  		switch sqlResult.AttributeIndex {
    76  		case int(common.ICAT_COLUMN_R_RESC_ID):
    77  			objID, err := strconv.ParseInt(value, 10, 64)
    78  			if err != nil {
    79  				return nil, xerrors.Errorf("failed to parse resource id '%s': %w", value, err)
    80  			}
    81  			resource.RescID = objID
    82  		case int(common.ICAT_COLUMN_R_RESC_NAME):
    83  			resource.Name = value
    84  		case int(common.ICAT_COLUMN_R_ZONE_NAME):
    85  			resource.Zone = value
    86  		case int(common.ICAT_COLUMN_R_TYPE_NAME):
    87  			resource.Type = value
    88  		case int(common.ICAT_COLUMN_R_CLASS_NAME):
    89  			resource.Class = value
    90  		case int(common.ICAT_COLUMN_R_LOC):
    91  			resource.Location = value
    92  		case int(common.ICAT_COLUMN_R_VAULT_PATH):
    93  			resource.Path = value
    94  		case int(common.ICAT_COLUMN_R_RESC_CONTEXT):
    95  			resource.Context = value
    96  		case int(common.ICAT_COLUMN_R_CREATE_TIME):
    97  			cT, err := util.GetIRODSDateTime(value)
    98  			if err != nil {
    99  				return nil, xerrors.Errorf("failed to parse create time '%s': %w", value, err)
   100  			}
   101  			resource.CreateTime = cT
   102  		case int(common.ICAT_COLUMN_R_MODIFY_TIME):
   103  			mT, err := util.GetIRODSDateTime(value)
   104  			if err != nil {
   105  				return nil, xerrors.Errorf("failed to parse modify time '%s': %w", value, err)
   106  			}
   107  			resource.ModifyTime = mT
   108  		default:
   109  			// ignore
   110  		}
   111  	}
   112  
   113  	return resource, nil
   114  }
   115  
   116  // AddResourceMeta sets metadata of a resource to the given key values.
   117  // metadata.AVUID is ignored
   118  func AddResourceMeta(conn *connection.IRODSConnection, name string, metadata *types.IRODSMeta) error {
   119  	if conn == nil || !conn.IsConnected() {
   120  		return xerrors.Errorf("connection is nil or disconnected")
   121  	}
   122  
   123  	// lock the connection
   124  	conn.Lock()
   125  	defer conn.Unlock()
   126  
   127  	request := message.NewIRODSMessageAddMetadataRequest(types.IRODSResourceMetaItemType, name, metadata)
   128  	response := message.IRODSMessageModifyMetadataResponse{}
   129  	err := conn.RequestAndCheck(request, &response, nil)
   130  	if err != nil {
   131  		return xerrors.Errorf("received an add data resource meta error: %w", err)
   132  	}
   133  	return nil
   134  }
   135  
   136  // DeleteResourceMeta sets metadata of a resource to the given key values.
   137  // The metadata AVU is selected on basis of AVUID if it is supplied, otherwise on basis of Name, Value and Units.
   138  func DeleteResourceMeta(conn *connection.IRODSConnection, name string, metadata *types.IRODSMeta) error {
   139  	if conn == nil || !conn.IsConnected() {
   140  		return xerrors.Errorf("connection is nil or disconnected")
   141  	}
   142  
   143  	// lock the connection
   144  	conn.Lock()
   145  	defer conn.Unlock()
   146  
   147  	var request *message.IRODSMessageModifyMetadataRequest
   148  
   149  	if metadata.AVUID != 0 {
   150  		request = message.NewIRODSMessageRemoveMetadataByIDRequest(types.IRODSResourceMetaItemType, name, metadata.AVUID)
   151  	} else if metadata.Units == "" && metadata.Value == "" {
   152  		request = message.NewIRODSMessageRemoveMetadataWildcardRequest(types.IRODSResourceMetaItemType, name, metadata.Name)
   153  	} else {
   154  		request = message.NewIRODSMessageRemoveMetadataRequest(types.IRODSResourceMetaItemType, name, metadata)
   155  	}
   156  
   157  	response := message.IRODSMessageModifyMetadataResponse{}
   158  	err := conn.RequestAndCheck(request, &response, nil)
   159  	if err != nil {
   160  		return xerrors.Errorf("received a delete data resource meta error: %w", err)
   161  	}
   162  	return nil
   163  }