text: #ifndef __IN_MEM_IO_H__
  #define __IN_MEM_IO_H__
  
  /*
   * Copyright 2014 Open Connectome Project (http://openconnecto.me)
   * Written by Da Zheng (zhengda1936@gmail.com)
   *
   * This file is part of SAFSlib.
   *
   * 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.
   */
  
  #include "NUMA_mapper.h"
  
  #include "io_interface.h"
  #include "comp_io_scheduler.h"
  #include "cache.h"
  
  namespace safs
  {
  
  class NUMA_buffer
  {
  	std::vector<std::shared_ptr<char> > bufs;
  	// This has the length of individual buffers.
  	// The sum of the physical buffer lengths >= the total length;
  	std::vector<size_t> buf_lens;
  	// This is the total length of the buffer.
  	size_t length;
  	NUMA_mapper mapper;
  
  	struct data_loc_info {
  		int node_id;
  		off_t local_off;
  		size_t local_size;
  		data_loc_info(int node_id, off_t local_off, size_t local_size) {
  			this->node_id = node_id;
  			this->local_off = local_off;
  			this->local_size = local_size;
  		}
  	};
  	data_loc_info get_data_loc(off_t off, size_t size) const;
  
  	NUMA_buffer(std::shared_ptr<char>, size_t length, const NUMA_mapper &mapper);
  	NUMA_buffer(size_t length, const NUMA_mapper &mapper);
  public:
  	typedef std::pair<const char *, size_t> cdata_info;
  	typedef std::pair<char *, size_t> data_info;
  	typedef std::shared_ptr<NUMA_buffer> ptr;
  
  	/*
  	 * Load data in a file to the buffer.
  	 */
  	static ptr load(const std::string &file, const NUMA_mapper &mapper);
  	static ptr load_safs(const std::string &file, const NUMA_mapper &mapper);
  
  	static ptr create(std::shared_ptr<char>, size_t length,
  			const NUMA_mapper &mapper);
  	static ptr create(size_t length, const NUMA_mapper &mapper) {
  		return ptr(new NUMA_buffer(length, mapper));
  	}
  
  	std::shared_ptr<char> get_buf(int node_id) {
  		if ((size_t) node_id >= bufs.size())
  			return std::shared_ptr<char>();
  		else
  			return bufs[node_id];
  	}
  
  	size_t get_num_nodes() const {
  		return mapper.get_num_nodes();
  	}
  
  	size_t get_length() const {
  		return length;
  	}
  
  	/*
  	 * Get the data in the specified location.
  	 * Since the data in the buffer isn't stored contiguously, the size of
  	 * the returned data may be smaller than the specified size.
  	 */
  	cdata_info get_data(off_t off, size_t size) const;
  	data_info get_data(off_t off, size_t size);
  
  	/*
  	 * Write the data in the given buffer to the specified location.
  	 */
  	void copy_from(const char *buf, size_t size, off_t off);
  	/*
  	 * Copy the data in the specified location to the given buffer.
  	 */
  	void copy_to(char *buf, size_t size, off_t off) const;
  
  	void dump(const std::string &file);
  };
  
  /*
   * This class provides a single I/O interface for accessing data in memory.
   * The main reason of having this class is to allow us to reuse a lot of code
   * when data is stored in memory.
   */
  class in_mem_io: public io_interface
  {
  	NUMA_buffer::ptr data;
  	int file_id;
  	fifo_queue<io_request> req_buf;
  	comp_io_scheduler::ptr comp_io_sched;
  	std::unique_ptr<byte_array_allocator> array_allocator;
  
  	callback::ptr cb;
  
  	void process_req(const io_request &req);
  	void process_computes();
  public:
  	in_mem_io(NUMA_buffer::ptr data, int file_id, thread *t);
  
  	virtual int get_file_id() const {
  		return file_id;
  	}
  
  	virtual bool support_aio() {
  		return true;
  	}
  
  	virtual bool set_callback(callback::ptr cb) {
  		this->cb = cb;
  		return true;
  	}
  
  	virtual bool have_callback() const {
  		return cb != NULL;
  	}
  
  	virtual callback &get_callback() {
  		return *cb;
  	}
  
  	virtual void flush_requests() { }
  
  	virtual int num_pending_ios() const {
  		return 0;
  	}
  
  	virtual io_status access(char *buf, off_t off, ssize_t size,
  			int access_method);
  	virtual void access(io_request *requests, int num, io_status *status);
  	virtual int wait4complete(int) {
  		return 0;
  	}
  	virtual std::shared_ptr<io_select> create_io_select() const;
  };
  
  class in_mem_io_factory: public file_io_factory
  {
  	// The I/O interface doesn't own the byte array.
  	NUMA_buffer::ptr data;
  	int file_id;
  public:
  	typedef std::shared_ptr<in_mem_io_factory> ptr;
  
  	in_mem_io_factory(NUMA_buffer::ptr data, int file_id,
  			const std::string file_name): file_io_factory(file_name) {
  		this->data = data;
  		this->file_id = file_id;
  	}
  
  	virtual int get_file_id() const {
  		return file_id;
  	}
  
  	virtual ssize_t get_file_size() const {
  		return data->get_length();
  	}
  
  	virtual io_interface::ptr create_io(thread *t) {
  		return io_interface::ptr(new in_mem_io(data, file_id, t));
  	}
  
  	virtual void destroy_io(io_interface &) {
  	}
  
  	const NUMA_buffer &get_data() const {
  		return *data;
  	}
  
  	NUMA_buffer &get_data() {
  		return *data;
  	}
  };
  
  }
  
  #endif
  