/* objectstore_carringo.c
*
* Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved.
* Copyright (c) 2015 OpenIO, as a part of Cyrus
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Carnegie Mellon University
* Center for Technology Transfer and Enterprise Creation
* 4615 Forbes Avenue
* Suite 302
* Pittsburgh, PA 15213
* (412) 268-7393, fax: (412) 268-7395
* innovation@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include "castor_sdk_c_interface.h"
#include "mailbox.h"
#include "mboxname.h"
#include "libconfig.h"
#include "xmalloc.h"
#include "util.h"
#include "objectstore.h"
#include "objectstore_db.h"
#define HTTP_OK 200
#define HTTP_CREATED 201
struct object_def
{
/* primary */
const char *user; // this is the container name.
const char *filename; // Name of blob
};
static const char *objectstore_get_object_filename(struct mailbox *mailbox, const struct index_record *record)
{
return message_guid_encode(&record->guid);
}
static struct object_def *objectstore_get_object_def (struct mailbox *mailbox, const struct index_record *record)
{
static struct object_def obj_def ;
obj_def.filename = objectstore_get_object_filename(mailbox, record) ;
obj_def.user = mboxname_to_userid(mailbox->name) ;
return &obj_def;
}
static int binit = 0 ;
static int init (void)
{
if (!binit){
binit = 1;
const char *host_name = config_getstring(IMAPOPT_CARINGO_HOSTNAME) ;
unsigned int port = config_getint (IMAPOPT_CARINGO_PORT) ;
unsigned int retries = 5 ;
unsigned int timeout = 300 ;
unsigned int maxclient = 1 ; // only one client per process.
open_client (host_name, port, retries, timeout, timeout, timeout, maxclient, maxclient);
}
return 0;
}
int objectstore_put (struct mailbox *mailbox, const struct index_record *record, const char *fname)
{
struct object_def *obj_def = NULL;
int already = 0 ;
int rc = 0;
rc = init () ;
if (rc) return rc;
obj_def = objectstore_get_object_def (mailbox, record);
// create user container if not there
if (info_bucket (obj_def->user) != HTTP_OK ){
create_bucket (obj_def->user) ;
}
add_message_guid (mailbox, record) ;
// check is file already exist
rc = objectstore_is_filename_in_container (mailbox, record, &already);
if (!already) {
struct buf buffer = BUF_INITIALIZER ;
struct stat sbuf;
int msgfd;
msgfd = open(fname, O_RDONLY, 0666);
if (msgfd == -1) {
syslog(LOG_ERR, "IOERROR: Cannot open %s", fname);
return msgfd;
}
if (fstat(msgfd, &sbuf) == -1) {
syslog(LOG_ERR, "IOERROR: fstat on %s", fname);
}
buf_init_mmap(&buffer, /*onceonly*/1, msgfd, fname, sbuf.st_size, mailbox->name);
close(msgfd);
rc = write_named_object (buffer.s, sbuf.st_size, obj_def->user, obj_def->filename) ;
if (rc == HTTP_CREATED ) {
syslog(LOG_INFO, "Carringo: file name %s write in bucket %s", fname, obj_def->user );
rc = 0;
} else {
syslog(LOG_ERR, "Carringo: file name %s write error: [record:%u] (%d) in bucket %s",
fname, record->uid, rc, obj_def->user );
rc = -1;
}
buf_free (&buffer) ;
}
return rc;
}
int objectstore_get (struct mailbox *mailbox, const struct index_record *record, const char *fname)
{
struct object_def *obj_def = NULL;
int rc = 0;
rc = init () ;
if (rc) return rc;
obj_def = objectstore_get_object_def (mailbox, record);
int len = info_named_object (obj_def->user, obj_def->filename) ;
if (len != -1) {
struct buf buffer = BUF_INITIALIZER ;
buf_ensure(&buffer, len+1);
rc = read_named_object (buffer.s, len, obj_def->user, obj_def->filename) ;
if (rc == HTTP_OK ) {
syslog(LOG_INFO, "Carringo: file name %s read from bucket %s", fname, obj_def->user );
rc = 0;
} else {
syslog(LOG_ERR, "Carringo: file name %s read error: [record:%u] (%d) from bucket %s",
fname, record->uid, rc, obj_def->user );
rc = -1 ;
}
if (rc != -1) {
//write filename
int fd;
fd = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0666);
if (fd == -1) {
syslog(LOG_ERR, "IOERROR: opening %s: %m", fname);
rc = -1 ;
}
else {
/* Write the file */
rc = write(fd, buffer.s, len );
if ( rc == len ) rc = 0 ;
else rc = -1;
}
buf_free (&buffer) ;
close (fd) ;
}
}
return rc;
}
int objectstore_delete (struct mailbox *mailbox, const struct index_record *record)
{
struct object_def *obj_def = NULL;
int rc = 0;
rc = init () ;
if (rc) return rc;
obj_def = objectstore_get_object_def (mailbox, record);
int count = 0;
delete_message_guid (mailbox, record, &count) ;
if (!count){
rc = delete_named_object (obj_def->user, obj_def->filename) ;
if (rc == HTTP_OK ) {
syslog(LOG_INFO, "Carringo: file name %s deleted from bucket %s", obj_def->filename, obj_def->user );
rc = 0;
} else {
syslog(LOG_ERR, "Carringo: file name %s delete error : [record:%u] (%d) from bucket %s",
obj_def->filename, record->uid, rc, obj_def->user );
rc = -1 ;
}
}
return rc;
}
int objectstore_is_filename_in_container (struct mailbox *mailbox, const struct index_record *record, int *isthere)
{
struct object_def *obj_def = NULL;
int rc = 0;
obj_def = objectstore_get_object_def (mailbox, record);
rc = info_named_object (obj_def->user, obj_def->filename) ;
if (rc > 0)
{
*isthere = 1 ;
return 0 ;
}
return rc ;
}